1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
#include <clock.h>
#include <init.h>
#include <of.h>
#include <gpio.h>
#include <linux/printk.h>
#include <linux/kernel.h>
#include <asm/armlinux.h>
#include <generated/mach-types.h>
static int rn2120_init(void)
{
/*
* This is the machine type that the kernel shipped by Netgear is using.
* It's wrong but a given fact.
*/
armlinux_set_architecture(MACH_TYPE_ARMADA_XP_DB);
return 0;
}
device_initcall(rn2120_init);
struct hdpower {
unsigned gpio_detect;
unsigned gpio_power;
unsigned gpio_led;
};
/*
* It would be nice to have this abstracted in the device tree, but currently
* this isn't the case.
*/
static struct hdpower rn2120_hdpower[] = {
{
/* sata 1 */
.gpio_detect = 32,
.gpio_power = 24,
.gpio_led = 31,
}, {
/* sata 2 */
.gpio_detect = 33,
.gpio_power = 25,
.gpio_led = 40,
}, {
/* sata 3 */
.gpio_detect = 34,
.gpio_power = 26,
.gpio_led = 44,
}, {
/* sata 4 */
.gpio_detect = 35,
.gpio_power = 28,
.gpio_led = 47,
},
};
static int rn2120_hddetect(void)
{
int i;
if (!of_machine_is_compatible("netgear,readynas-2120"))
return 0;
for (i = 0; i < ARRAY_SIZE(rn2120_hdpower); ++i) {
int ret;
ret = gpio_direction_input(rn2120_hdpower[i].gpio_detect);
if (ret) {
pr_err("Failure to detect hd%d (%d)\n", i, ret);
continue;
}
ret = gpio_get_value(rn2120_hdpower[i].gpio_detect);
if (ret) {
/* no disk present */
gpio_direction_output(rn2120_hdpower[i].gpio_power, 0);
} else {
pr_info("Detected presence of disk #%d\n", i + 1);
/* make a pause after powering up 2 disks */
if (i && !(i & 1)) {
pr_info("Delay power up\n");
mdelay(7000);
}
gpio_direction_output(rn2120_hdpower[i].gpio_power, 1);
}
}
return 0;
}
device_initcall(rn2120_hddetect);
|