diff options
Diffstat (limited to 'drivers')
55 files changed, 3092 insertions, 373 deletions
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index e7ba774beda6..25373df1dcf8 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c | |||
| @@ -566,6 +566,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_ | |||
| 566 | struct mailbox mailbox; | 566 | struct mailbox mailbox; |
| 567 | 567 | ||
| 568 | /* Got a packet for us */ | 568 | /* Got a packet for us */ |
| 569 | memset(&st_loc, 0, sizeof(st_loc)); | ||
| 569 | ret = do_ac_read(i, buf, &st_loc, &mailbox); | 570 | ret = do_ac_read(i, buf, &st_loc, &mailbox); |
| 570 | spin_unlock_irqrestore(&apbs[i].mutex, flags); | 571 | spin_unlock_irqrestore(&apbs[i].mutex, flags); |
| 571 | set_current_state(TASK_RUNNING); | 572 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 3afd62e856eb..e9cba13ee800 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
| @@ -713,7 +713,6 @@ static int khvcd(void *unused) | |||
| 713 | struct hvc_struct *hp; | 713 | struct hvc_struct *hp; |
| 714 | 714 | ||
| 715 | set_freezable(); | 715 | set_freezable(); |
| 716 | __set_current_state(TASK_RUNNING); | ||
| 717 | do { | 716 | do { |
| 718 | poll_mask = 0; | 717 | poll_mask = 0; |
| 719 | hvc_kicked = 0; | 718 | hvc_kicked = 0; |
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile index bc397d92b499..7b78e0dfc5b0 100644 --- a/drivers/char/ip2/Makefile +++ b/drivers/char/ip2/Makefile | |||
| @@ -4,5 +4,5 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_COMPUTONE) += ip2.o | 5 | obj-$(CONFIG_COMPUTONE) += ip2.o |
| 6 | 6 | ||
| 7 | ip2-objs := ip2main.o | 7 | ip2-y := ip2main.o |
| 8 | 8 | ||
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index eb8a1a8c188e..16a93648d54e 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # Makefile for the ipmi drivers. | 2 | # Makefile for the ipmi drivers. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | ipmi_si-objs := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o | 5 | ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o | 7 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o |
| 8 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o | 8 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 1fc8876af1f5..2aa3977aae5e 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
| @@ -916,7 +916,7 @@ static struct ipmi_smi_watcher smi_watcher = | |||
| 916 | .smi_gone = ipmi_smi_gone, | 916 | .smi_gone = ipmi_smi_gone, |
| 917 | }; | 917 | }; |
| 918 | 918 | ||
| 919 | static __init int init_ipmi_devintf(void) | 919 | static int __init init_ipmi_devintf(void) |
| 920 | { | 920 | { |
| 921 | int rv; | 921 | int rv; |
| 922 | 922 | ||
| @@ -954,7 +954,7 @@ static __init int init_ipmi_devintf(void) | |||
| 954 | } | 954 | } |
| 955 | module_init(init_ipmi_devintf); | 955 | module_init(init_ipmi_devintf); |
| 956 | 956 | ||
| 957 | static __exit void cleanup_ipmi(void) | 957 | static void __exit cleanup_ipmi(void) |
| 958 | { | 958 | { |
| 959 | struct ipmi_reg_list *entry, *entry2; | 959 | struct ipmi_reg_list *entry, *entry2; |
| 960 | mutex_lock(®_list_mutex); | 960 | mutex_lock(®_list_mutex); |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 4f3f8c9ec262..2fe72f8edf44 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -4442,13 +4442,13 @@ static int ipmi_init_msghandler(void) | |||
| 4442 | return 0; | 4442 | return 0; |
| 4443 | } | 4443 | } |
| 4444 | 4444 | ||
| 4445 | static __init int ipmi_init_msghandler_mod(void) | 4445 | static int __init ipmi_init_msghandler_mod(void) |
| 4446 | { | 4446 | { |
| 4447 | ipmi_init_msghandler(); | 4447 | ipmi_init_msghandler(); |
| 4448 | return 0; | 4448 | return 0; |
| 4449 | } | 4449 | } |
| 4450 | 4450 | ||
| 4451 | static __exit void cleanup_ipmi(void) | 4451 | static void __exit cleanup_ipmi(void) |
| 4452 | { | 4452 | { |
| 4453 | int count; | 4453 | int count; |
| 4454 | 4454 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index b293d57d30a7..035da9e64a17 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -1846,7 +1846,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
| 1846 | return rv; | 1846 | return rv; |
| 1847 | } | 1847 | } |
| 1848 | 1848 | ||
| 1849 | static __devinit void hardcode_find_bmc(void) | 1849 | static void __devinit hardcode_find_bmc(void) |
| 1850 | { | 1850 | { |
| 1851 | int i; | 1851 | int i; |
| 1852 | struct smi_info *info; | 1852 | struct smi_info *info; |
| @@ -2029,7 +2029,7 @@ struct SPMITable { | |||
| 2029 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ | 2029 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ |
| 2030 | }; | 2030 | }; |
| 2031 | 2031 | ||
| 2032 | static __devinit int try_init_spmi(struct SPMITable *spmi) | 2032 | static int __devinit try_init_spmi(struct SPMITable *spmi) |
| 2033 | { | 2033 | { |
| 2034 | struct smi_info *info; | 2034 | struct smi_info *info; |
| 2035 | 2035 | ||
| @@ -2112,7 +2112,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
| 2112 | return 0; | 2112 | return 0; |
| 2113 | } | 2113 | } |
| 2114 | 2114 | ||
| 2115 | static __devinit void spmi_find_bmc(void) | 2115 | static void __devinit spmi_find_bmc(void) |
| 2116 | { | 2116 | { |
| 2117 | acpi_status status; | 2117 | acpi_status status; |
| 2118 | struct SPMITable *spmi; | 2118 | struct SPMITable *spmi; |
| @@ -2325,7 +2325,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm, | |||
| 2325 | return 0; | 2325 | return 0; |
| 2326 | } | 2326 | } |
| 2327 | 2327 | ||
| 2328 | static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | 2328 | static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data) |
| 2329 | { | 2329 | { |
| 2330 | struct smi_info *info; | 2330 | struct smi_info *info; |
| 2331 | 2331 | ||
| @@ -3012,7 +3012,7 @@ static __devinitdata struct ipmi_default_vals | |||
| 3012 | { .port = 0 } | 3012 | { .port = 0 } |
| 3013 | }; | 3013 | }; |
| 3014 | 3014 | ||
| 3015 | static __devinit void default_find_bmc(void) | 3015 | static void __devinit default_find_bmc(void) |
| 3016 | { | 3016 | { |
| 3017 | struct smi_info *info; | 3017 | struct smi_info *info; |
| 3018 | int i; | 3018 | int i; |
| @@ -3312,7 +3312,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
| 3312 | return rv; | 3312 | return rv; |
| 3313 | } | 3313 | } |
| 3314 | 3314 | ||
| 3315 | static __devinit int init_ipmi_si(void) | 3315 | static int __devinit init_ipmi_si(void) |
| 3316 | { | 3316 | { |
| 3317 | int i; | 3317 | int i; |
| 3318 | char *str; | 3318 | char *str; |
| @@ -3525,7 +3525,7 @@ static void cleanup_one_si(struct smi_info *to_clean) | |||
| 3525 | kfree(to_clean); | 3525 | kfree(to_clean); |
| 3526 | } | 3526 | } |
| 3527 | 3527 | ||
| 3528 | static __exit void cleanup_ipmi_si(void) | 3528 | static void __exit cleanup_ipmi_si(void) |
| 3529 | { | 3529 | { |
| 3530 | struct smi_info *e, *tmp_e; | 3530 | struct smi_info *e, *tmp_e; |
| 3531 | 3531 | ||
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index c070b53984e4..e6d75627c6c8 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c | |||
| @@ -176,9 +176,9 @@ static void mmtimer_setup_int_2(int cpu, u64 expires) | |||
| 176 | * in order to insure that the setup succeeds in a deterministic time frame. | 176 | * in order to insure that the setup succeeds in a deterministic time frame. |
| 177 | * It will check if the interrupt setup succeeded. | 177 | * It will check if the interrupt setup succeeded. |
| 178 | */ | 178 | */ |
| 179 | static int mmtimer_setup(int cpu, int comparator, unsigned long expires) | 179 | static int mmtimer_setup(int cpu, int comparator, unsigned long expires, |
| 180 | u64 *set_completion_time) | ||
| 180 | { | 181 | { |
| 181 | |||
| 182 | switch (comparator) { | 182 | switch (comparator) { |
| 183 | case 0: | 183 | case 0: |
| 184 | mmtimer_setup_int_0(cpu, expires); | 184 | mmtimer_setup_int_0(cpu, expires); |
| @@ -191,7 +191,8 @@ static int mmtimer_setup(int cpu, int comparator, unsigned long expires) | |||
| 191 | break; | 191 | break; |
| 192 | } | 192 | } |
| 193 | /* We might've missed our expiration time */ | 193 | /* We might've missed our expiration time */ |
| 194 | if (rtc_time() <= expires) | 194 | *set_completion_time = rtc_time(); |
| 195 | if (*set_completion_time <= expires) | ||
| 195 | return 1; | 196 | return 1; |
| 196 | 197 | ||
| 197 | /* | 198 | /* |
| @@ -227,6 +228,8 @@ static int mmtimer_disable_int(long nasid, int comparator) | |||
| 227 | #define TIMER_OFF 0xbadcabLL /* Timer is not setup */ | 228 | #define TIMER_OFF 0xbadcabLL /* Timer is not setup */ |
| 228 | #define TIMER_SET 0 /* Comparator is set for this timer */ | 229 | #define TIMER_SET 0 /* Comparator is set for this timer */ |
| 229 | 230 | ||
| 231 | #define MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT 40 | ||
| 232 | |||
| 230 | /* There is one of these for each timer */ | 233 | /* There is one of these for each timer */ |
| 231 | struct mmtimer { | 234 | struct mmtimer { |
| 232 | struct rb_node list; | 235 | struct rb_node list; |
| @@ -242,6 +245,11 @@ struct mmtimer_node { | |||
| 242 | }; | 245 | }; |
| 243 | static struct mmtimer_node *timers; | 246 | static struct mmtimer_node *timers; |
| 244 | 247 | ||
| 248 | static unsigned mmtimer_interval_retry_increment = | ||
| 249 | MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT; | ||
| 250 | module_param(mmtimer_interval_retry_increment, uint, 0644); | ||
| 251 | MODULE_PARM_DESC(mmtimer_interval_retry_increment, | ||
| 252 | "RTC ticks to add to expiration on interval retry (default 40)"); | ||
| 245 | 253 | ||
| 246 | /* | 254 | /* |
| 247 | * Add a new mmtimer struct to the node's mmtimer list. | 255 | * Add a new mmtimer struct to the node's mmtimer list. |
| @@ -289,7 +297,8 @@ static void mmtimer_set_next_timer(int nodeid) | |||
| 289 | struct mmtimer_node *n = &timers[nodeid]; | 297 | struct mmtimer_node *n = &timers[nodeid]; |
| 290 | struct mmtimer *x; | 298 | struct mmtimer *x; |
| 291 | struct k_itimer *t; | 299 | struct k_itimer *t; |
| 292 | int o; | 300 | u64 expires, exp, set_completion_time; |
| 301 | int i; | ||
| 293 | 302 | ||
| 294 | restart: | 303 | restart: |
| 295 | if (n->next == NULL) | 304 | if (n->next == NULL) |
| @@ -300,7 +309,8 @@ restart: | |||
| 300 | if (!t->it.mmtimer.incr) { | 309 | if (!t->it.mmtimer.incr) { |
| 301 | /* Not an interval timer */ | 310 | /* Not an interval timer */ |
| 302 | if (!mmtimer_setup(x->cpu, COMPARATOR, | 311 | if (!mmtimer_setup(x->cpu, COMPARATOR, |
| 303 | t->it.mmtimer.expires)) { | 312 | t->it.mmtimer.expires, |
| 313 | &set_completion_time)) { | ||
| 304 | /* Late setup, fire now */ | 314 | /* Late setup, fire now */ |
| 305 | tasklet_schedule(&n->tasklet); | 315 | tasklet_schedule(&n->tasklet); |
| 306 | } | 316 | } |
| @@ -308,14 +318,23 @@ restart: | |||
| 308 | } | 318 | } |
| 309 | 319 | ||
| 310 | /* Interval timer */ | 320 | /* Interval timer */ |
| 311 | o = 0; | 321 | i = 0; |
| 312 | while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) { | 322 | expires = exp = t->it.mmtimer.expires; |
| 313 | unsigned long e, e1; | 323 | while (!mmtimer_setup(x->cpu, COMPARATOR, expires, |
| 314 | struct rb_node *next; | 324 | &set_completion_time)) { |
| 315 | t->it.mmtimer.expires += t->it.mmtimer.incr << o; | 325 | int to; |
| 316 | t->it_overrun += 1 << o; | 326 | |
| 317 | o++; | 327 | i++; |
| 318 | if (o > 20) { | 328 | expires = set_completion_time + |
| 329 | mmtimer_interval_retry_increment + (1 << i); | ||
| 330 | /* Calculate overruns as we go. */ | ||
| 331 | to = ((u64)(expires - exp) / t->it.mmtimer.incr); | ||
| 332 | if (to) { | ||
| 333 | t->it_overrun += to; | ||
| 334 | t->it.mmtimer.expires += t->it.mmtimer.incr * to; | ||
| 335 | exp = t->it.mmtimer.expires; | ||
| 336 | } | ||
| 337 | if (i > 20) { | ||
| 319 | printk(KERN_ALERT "mmtimer: cannot reschedule timer\n"); | 338 | printk(KERN_ALERT "mmtimer: cannot reschedule timer\n"); |
| 320 | t->it.mmtimer.clock = TIMER_OFF; | 339 | t->it.mmtimer.clock = TIMER_OFF; |
| 321 | n->next = rb_next(&x->list); | 340 | n->next = rb_next(&x->list); |
| @@ -323,21 +342,6 @@ restart: | |||
| 323 | kfree(x); | 342 | kfree(x); |
| 324 | goto restart; | 343 | goto restart; |
| 325 | } | 344 | } |
| 326 | |||
| 327 | e = t->it.mmtimer.expires; | ||
| 328 | next = rb_next(&x->list); | ||
| 329 | |||
| 330 | if (next == NULL) | ||
| 331 | continue; | ||
| 332 | |||
| 333 | e1 = rb_entry(next, struct mmtimer, list)-> | ||
| 334 | timer->it.mmtimer.expires; | ||
| 335 | if (e > e1) { | ||
| 336 | n->next = next; | ||
| 337 | rb_erase(&x->list, &n->timer_head); | ||
| 338 | mmtimer_add_list(x); | ||
| 339 | goto restart; | ||
| 340 | } | ||
| 341 | } | 345 | } |
| 342 | } | 346 | } |
| 343 | 347 | ||
diff --git a/drivers/char/mwave/Makefile b/drivers/char/mwave/Makefile index 754c9e2058ed..26b4fce217b6 100644 --- a/drivers/char/mwave/Makefile +++ b/drivers/char/mwave/Makefile | |||
| @@ -6,10 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | obj-$(CONFIG_MWAVE) += mwave.o | 7 | obj-$(CONFIG_MWAVE) += mwave.o |
| 8 | 8 | ||
| 9 | mwave-objs := mwavedd.o smapi.o tp3780i.o 3780i.o | 9 | mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o |
| 10 | 10 | ||
| 11 | # To have the mwave driver disable other uarts if necessary | 11 | # To have the mwave driver disable other uarts if necessary |
| 12 | # EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES | 12 | # EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES |
| 13 | 13 | ||
| 14 | # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging: | 14 | # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging: |
| 15 | EXTRA_CFLAGS += -DMW_TRACE | 15 | ccflags-y := -DMW_TRACE |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 463df27494bd..dd9d75351cd6 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
| @@ -303,6 +303,7 @@ static void mxser_enable_must_enchance_mode(unsigned long baseio) | |||
| 303 | outb(oldlcr, baseio + UART_LCR); | 303 | outb(oldlcr, baseio + UART_LCR); |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | #ifdef CONFIG_PCI | ||
| 306 | static void mxser_disable_must_enchance_mode(unsigned long baseio) | 307 | static void mxser_disable_must_enchance_mode(unsigned long baseio) |
| 307 | { | 308 | { |
| 308 | u8 oldlcr; | 309 | u8 oldlcr; |
| @@ -317,6 +318,7 @@ static void mxser_disable_must_enchance_mode(unsigned long baseio) | |||
| 317 | outb(efr, baseio + MOXA_MUST_EFR_REGISTER); | 318 | outb(efr, baseio + MOXA_MUST_EFR_REGISTER); |
| 318 | outb(oldlcr, baseio + UART_LCR); | 319 | outb(oldlcr, baseio + UART_LCR); |
| 319 | } | 320 | } |
| 321 | #endif | ||
| 320 | 322 | ||
| 321 | static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) | 323 | static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) |
| 322 | { | 324 | { |
| @@ -388,6 +390,7 @@ static void mxser_set_must_enum_value(unsigned long baseio, u8 value) | |||
| 388 | outb(oldlcr, baseio + UART_LCR); | 390 | outb(oldlcr, baseio + UART_LCR); |
| 389 | } | 391 | } |
| 390 | 392 | ||
| 393 | #ifdef CONFIG_PCI | ||
| 391 | static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) | 394 | static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) |
| 392 | { | 395 | { |
| 393 | u8 oldlcr; | 396 | u8 oldlcr; |
| @@ -404,6 +407,7 @@ static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) | |||
| 404 | *pId = inb(baseio + MOXA_MUST_HWID_REGISTER); | 407 | *pId = inb(baseio + MOXA_MUST_HWID_REGISTER); |
| 405 | outb(oldlcr, baseio + UART_LCR); | 408 | outb(oldlcr, baseio + UART_LCR); |
| 406 | } | 409 | } |
| 410 | #endif | ||
| 407 | 411 | ||
| 408 | static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) | 412 | static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) |
| 409 | { | 413 | { |
diff --git a/drivers/char/pcmcia/ipwireless/Makefile b/drivers/char/pcmcia/ipwireless/Makefile index b71eb593643d..db80873d7f20 100644 --- a/drivers/char/pcmcia/ipwireless/Makefile +++ b/drivers/char/pcmcia/ipwireless/Makefile | |||
| @@ -6,5 +6,5 @@ | |||
| 6 | 6 | ||
| 7 | obj-$(CONFIG_IPWIRELESS) += ipwireless.o | 7 | obj-$(CONFIG_IPWIRELESS) += ipwireless.o |
| 8 | 8 | ||
| 9 | ipwireless-objs := hardware.o main.o network.o tty.o | 9 | ipwireless-y := hardware.o main.o network.o tty.o |
| 10 | 10 | ||
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 723152d978a9..f176dbaeb15a 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
| @@ -613,6 +613,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 613 | 613 | ||
| 614 | case PPGETTIME: | 614 | case PPGETTIME: |
| 615 | to_jiffies = pp->pdev->timeout; | 615 | to_jiffies = pp->pdev->timeout; |
| 616 | memset(&par_timeout, 0, sizeof(par_timeout)); | ||
| 616 | par_timeout.tv_sec = to_jiffies / HZ; | 617 | par_timeout.tv_sec = to_jiffies / HZ; |
| 617 | par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); | 618 | par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); |
| 618 | if (copy_to_user (argp, &par_timeout, sizeof(struct timeval))) | 619 | if (copy_to_user (argp, &par_timeout, sizeof(struct timeval))) |
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c index 74f00b5ffa36..73dcb0ee41fd 100644 --- a/drivers/char/ramoops.c +++ b/drivers/char/ramoops.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
| 28 | #include <linux/platform_device.h> | ||
| 29 | #include <linux/ramoops.h> | ||
| 28 | 30 | ||
| 29 | #define RAMOOPS_KERNMSG_HDR "====" | 31 | #define RAMOOPS_KERNMSG_HDR "====" |
| 30 | #define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval)) | 32 | #define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval)) |
| @@ -91,11 +93,17 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, | |||
| 91 | cxt->count = (cxt->count + 1) % cxt->max_count; | 93 | cxt->count = (cxt->count + 1) % cxt->max_count; |
| 92 | } | 94 | } |
| 93 | 95 | ||
| 94 | static int __init ramoops_init(void) | 96 | static int __init ramoops_probe(struct platform_device *pdev) |
| 95 | { | 97 | { |
| 98 | struct ramoops_platform_data *pdata = pdev->dev.platform_data; | ||
| 96 | struct ramoops_context *cxt = &oops_cxt; | 99 | struct ramoops_context *cxt = &oops_cxt; |
| 97 | int err = -EINVAL; | 100 | int err = -EINVAL; |
| 98 | 101 | ||
| 102 | if (pdata) { | ||
| 103 | mem_size = pdata->mem_size; | ||
| 104 | mem_address = pdata->mem_address; | ||
| 105 | } | ||
| 106 | |||
| 99 | if (!mem_size) { | 107 | if (!mem_size) { |
| 100 | printk(KERN_ERR "ramoops: invalid size specification"); | 108 | printk(KERN_ERR "ramoops: invalid size specification"); |
| 101 | goto fail3; | 109 | goto fail3; |
| @@ -142,7 +150,7 @@ fail3: | |||
| 142 | return err; | 150 | return err; |
| 143 | } | 151 | } |
| 144 | 152 | ||
| 145 | static void __exit ramoops_exit(void) | 153 | static int __exit ramoops_remove(struct platform_device *pdev) |
| 146 | { | 154 | { |
| 147 | struct ramoops_context *cxt = &oops_cxt; | 155 | struct ramoops_context *cxt = &oops_cxt; |
| 148 | 156 | ||
| @@ -151,8 +159,26 @@ static void __exit ramoops_exit(void) | |||
| 151 | 159 | ||
| 152 | iounmap(cxt->virt_addr); | 160 | iounmap(cxt->virt_addr); |
| 153 | release_mem_region(cxt->phys_addr, cxt->size); | 161 | release_mem_region(cxt->phys_addr, cxt->size); |
| 162 | return 0; | ||
| 154 | } | 163 | } |
| 155 | 164 | ||
| 165 | static struct platform_driver ramoops_driver = { | ||
| 166 | .remove = __exit_p(ramoops_remove), | ||
| 167 | .driver = { | ||
| 168 | .name = "ramoops", | ||
| 169 | .owner = THIS_MODULE, | ||
| 170 | }, | ||
| 171 | }; | ||
| 172 | |||
| 173 | static int __init ramoops_init(void) | ||
| 174 | { | ||
| 175 | return platform_driver_probe(&ramoops_driver, ramoops_probe); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void __exit ramoops_exit(void) | ||
| 179 | { | ||
| 180 | platform_driver_unregister(&ramoops_driver); | ||
| 181 | } | ||
| 156 | 182 | ||
| 157 | module_init(ramoops_init); | 183 | module_init(ramoops_init); |
| 158 | module_exit(ramoops_exit); | 184 | module_exit(ramoops_exit); |
diff --git a/drivers/char/rio/Makefile b/drivers/char/rio/Makefile index 2d1c5a7cba7d..1661875883fb 100644 --- a/drivers/char/rio/Makefile +++ b/drivers/char/rio/Makefile | |||
| @@ -8,5 +8,5 @@ | |||
| 8 | 8 | ||
| 9 | obj-$(CONFIG_RIO) += rio.o | 9 | obj-$(CONFIG_RIO) += rio.o |
| 10 | 10 | ||
| 11 | rio-objs := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ | 11 | rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ |
| 12 | rioparam.o rioroute.o riotable.o riotty.o | 12 | rioparam.o rioroute.o riotable.o riotty.o |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 7c79d243acc9..86308830ac42 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
| @@ -2345,7 +2345,7 @@ static int __init rp_init(void) | |||
| 2345 | ret = tty_register_driver(rocket_driver); | 2345 | ret = tty_register_driver(rocket_driver); |
| 2346 | if (ret < 0) { | 2346 | if (ret < 0) { |
| 2347 | printk(KERN_ERR "Couldn't install tty RocketPort driver\n"); | 2347 | printk(KERN_ERR "Couldn't install tty RocketPort driver\n"); |
| 2348 | goto err_tty; | 2348 | goto err_controller; |
| 2349 | } | 2349 | } |
| 2350 | 2350 | ||
| 2351 | #ifdef ROCKET_DEBUG_OPEN | 2351 | #ifdef ROCKET_DEBUG_OPEN |
| @@ -2380,6 +2380,9 @@ static int __init rp_init(void) | |||
| 2380 | return 0; | 2380 | return 0; |
| 2381 | err_ttyu: | 2381 | err_ttyu: |
| 2382 | tty_unregister_driver(rocket_driver); | 2382 | tty_unregister_driver(rocket_driver); |
| 2383 | err_controller: | ||
| 2384 | if (controller) | ||
| 2385 | release_region(controller, 4); | ||
| 2383 | err_tty: | 2386 | err_tty: |
| 2384 | put_tty_driver(rocket_driver); | 2387 | put_tty_driver(rocket_driver); |
| 2385 | err: | 2388 | err: |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 1746d91205f7..d01fffeac951 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
| @@ -301,6 +301,8 @@ struct slgt_info { | |||
| 301 | unsigned int rx_pio; | 301 | unsigned int rx_pio; |
| 302 | unsigned int if_mode; | 302 | unsigned int if_mode; |
| 303 | unsigned int base_clock; | 303 | unsigned int base_clock; |
| 304 | unsigned int xsync; | ||
| 305 | unsigned int xctrl; | ||
| 304 | 306 | ||
| 305 | /* device status */ | 307 | /* device status */ |
| 306 | 308 | ||
| @@ -405,6 +407,8 @@ static MGSL_PARAMS default_params = { | |||
| 405 | #define TDCSR 0x94 /* tx DMA control/status */ | 407 | #define TDCSR 0x94 /* tx DMA control/status */ |
| 406 | #define RDDAR 0x98 /* rx DMA descriptor address */ | 408 | #define RDDAR 0x98 /* rx DMA descriptor address */ |
| 407 | #define TDDAR 0x9c /* tx DMA descriptor address */ | 409 | #define TDDAR 0x9c /* tx DMA descriptor address */ |
| 410 | #define XSR 0x40 /* extended sync pattern */ | ||
| 411 | #define XCR 0x44 /* extended control */ | ||
| 408 | 412 | ||
| 409 | #define RXIDLE BIT14 | 413 | #define RXIDLE BIT14 |
| 410 | #define RXBREAK BIT14 | 414 | #define RXBREAK BIT14 |
| @@ -517,6 +521,10 @@ static int set_interface(struct slgt_info *info, int if_mode); | |||
| 517 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 521 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
| 518 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 522 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
| 519 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 523 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
| 524 | static int get_xsync(struct slgt_info *info, int __user *if_mode); | ||
| 525 | static int set_xsync(struct slgt_info *info, int if_mode); | ||
| 526 | static int get_xctrl(struct slgt_info *info, int __user *if_mode); | ||
| 527 | static int set_xctrl(struct slgt_info *info, int if_mode); | ||
| 520 | 528 | ||
| 521 | /* | 529 | /* |
| 522 | * driver functions | 530 | * driver functions |
| @@ -1056,6 +1064,14 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
| 1056 | return get_gpio(info, argp); | 1064 | return get_gpio(info, argp); |
| 1057 | case MGSL_IOCWAITGPIO: | 1065 | case MGSL_IOCWAITGPIO: |
| 1058 | return wait_gpio(info, argp); | 1066 | return wait_gpio(info, argp); |
| 1067 | case MGSL_IOCGXSYNC: | ||
| 1068 | return get_xsync(info, argp); | ||
| 1069 | case MGSL_IOCSXSYNC: | ||
| 1070 | return set_xsync(info, (int)arg); | ||
| 1071 | case MGSL_IOCGXCTRL: | ||
| 1072 | return get_xctrl(info, argp); | ||
| 1073 | case MGSL_IOCSXCTRL: | ||
| 1074 | return set_xctrl(info, (int)arg); | ||
| 1059 | } | 1075 | } |
| 1060 | mutex_lock(&info->port.mutex); | 1076 | mutex_lock(&info->port.mutex); |
| 1061 | switch (cmd) { | 1077 | switch (cmd) { |
| @@ -1132,6 +1148,7 @@ static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *us | |||
| 1132 | struct MGSL_PARAMS32 tmp_params; | 1148 | struct MGSL_PARAMS32 tmp_params; |
| 1133 | 1149 | ||
| 1134 | DBGINFO(("%s get_params32\n", info->device_name)); | 1150 | DBGINFO(("%s get_params32\n", info->device_name)); |
| 1151 | memset(&tmp_params, 0, sizeof(tmp_params)); | ||
| 1135 | tmp_params.mode = (compat_ulong_t)info->params.mode; | 1152 | tmp_params.mode = (compat_ulong_t)info->params.mode; |
| 1136 | tmp_params.loopback = info->params.loopback; | 1153 | tmp_params.loopback = info->params.loopback; |
| 1137 | tmp_params.flags = info->params.flags; | 1154 | tmp_params.flags = info->params.flags; |
| @@ -1212,12 +1229,16 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1212 | case MGSL_IOCSGPIO: | 1229 | case MGSL_IOCSGPIO: |
| 1213 | case MGSL_IOCGGPIO: | 1230 | case MGSL_IOCGGPIO: |
| 1214 | case MGSL_IOCWAITGPIO: | 1231 | case MGSL_IOCWAITGPIO: |
| 1232 | case MGSL_IOCGXSYNC: | ||
| 1233 | case MGSL_IOCGXCTRL: | ||
| 1215 | case MGSL_IOCSTXIDLE: | 1234 | case MGSL_IOCSTXIDLE: |
| 1216 | case MGSL_IOCTXENABLE: | 1235 | case MGSL_IOCTXENABLE: |
| 1217 | case MGSL_IOCRXENABLE: | 1236 | case MGSL_IOCRXENABLE: |
| 1218 | case MGSL_IOCTXABORT: | 1237 | case MGSL_IOCTXABORT: |
| 1219 | case TIOCMIWAIT: | 1238 | case TIOCMIWAIT: |
| 1220 | case MGSL_IOCSIF: | 1239 | case MGSL_IOCSIF: |
| 1240 | case MGSL_IOCSXSYNC: | ||
| 1241 | case MGSL_IOCSXCTRL: | ||
| 1221 | rc = ioctl(tty, file, cmd, arg); | 1242 | rc = ioctl(tty, file, cmd, arg); |
| 1222 | break; | 1243 | break; |
| 1223 | } | 1244 | } |
| @@ -1617,6 +1638,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 1617 | if (cmd != SIOCWANDEV) | 1638 | if (cmd != SIOCWANDEV) |
| 1618 | return hdlc_ioctl(dev, ifr, cmd); | 1639 | return hdlc_ioctl(dev, ifr, cmd); |
| 1619 | 1640 | ||
| 1641 | memset(&new_line, 0, sizeof(new_line)); | ||
| 1642 | |||
| 1620 | switch(ifr->ifr_settings.type) { | 1643 | switch(ifr->ifr_settings.type) { |
| 1621 | case IF_GET_IFACE: /* return current sync_serial_settings */ | 1644 | case IF_GET_IFACE: /* return current sync_serial_settings */ |
| 1622 | 1645 | ||
| @@ -1958,6 +1981,7 @@ static void bh_handler(struct work_struct *work) | |||
| 1958 | case MGSL_MODE_RAW: | 1981 | case MGSL_MODE_RAW: |
| 1959 | case MGSL_MODE_MONOSYNC: | 1982 | case MGSL_MODE_MONOSYNC: |
| 1960 | case MGSL_MODE_BISYNC: | 1983 | case MGSL_MODE_BISYNC: |
| 1984 | case MGSL_MODE_XSYNC: | ||
| 1961 | while(rx_get_buf(info)); | 1985 | while(rx_get_buf(info)); |
| 1962 | break; | 1986 | break; |
| 1963 | } | 1987 | } |
| @@ -2357,26 +2381,27 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id) | |||
| 2357 | 2381 | ||
| 2358 | DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); | 2382 | DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); |
| 2359 | 2383 | ||
| 2360 | spin_lock(&info->lock); | ||
| 2361 | |||
| 2362 | while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { | 2384 | while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { |
| 2363 | DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); | 2385 | DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); |
| 2364 | info->irq_occurred = true; | 2386 | info->irq_occurred = true; |
| 2365 | for(i=0; i < info->port_count ; i++) { | 2387 | for(i=0; i < info->port_count ; i++) { |
| 2366 | if (info->port_array[i] == NULL) | 2388 | if (info->port_array[i] == NULL) |
| 2367 | continue; | 2389 | continue; |
| 2390 | spin_lock(&info->port_array[i]->lock); | ||
| 2368 | if (gsr & (BIT8 << i)) | 2391 | if (gsr & (BIT8 << i)) |
| 2369 | isr_serial(info->port_array[i]); | 2392 | isr_serial(info->port_array[i]); |
| 2370 | if (gsr & (BIT16 << (i*2))) | 2393 | if (gsr & (BIT16 << (i*2))) |
| 2371 | isr_rdma(info->port_array[i]); | 2394 | isr_rdma(info->port_array[i]); |
| 2372 | if (gsr & (BIT17 << (i*2))) | 2395 | if (gsr & (BIT17 << (i*2))) |
| 2373 | isr_tdma(info->port_array[i]); | 2396 | isr_tdma(info->port_array[i]); |
| 2397 | spin_unlock(&info->port_array[i]->lock); | ||
| 2374 | } | 2398 | } |
| 2375 | } | 2399 | } |
| 2376 | 2400 | ||
| 2377 | if (info->gpio_present) { | 2401 | if (info->gpio_present) { |
| 2378 | unsigned int state; | 2402 | unsigned int state; |
| 2379 | unsigned int changed; | 2403 | unsigned int changed; |
| 2404 | spin_lock(&info->lock); | ||
| 2380 | while ((changed = rd_reg32(info, IOSR)) != 0) { | 2405 | while ((changed = rd_reg32(info, IOSR)) != 0) { |
| 2381 | DBGISR(("%s iosr=%08x\n", info->device_name, changed)); | 2406 | DBGISR(("%s iosr=%08x\n", info->device_name, changed)); |
| 2382 | /* read latched state of GPIO signals */ | 2407 | /* read latched state of GPIO signals */ |
| @@ -2388,22 +2413,24 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id) | |||
| 2388 | isr_gpio(info->port_array[i], changed, state); | 2413 | isr_gpio(info->port_array[i], changed, state); |
| 2389 | } | 2414 | } |
| 2390 | } | 2415 | } |
| 2416 | spin_unlock(&info->lock); | ||
| 2391 | } | 2417 | } |
| 2392 | 2418 | ||
| 2393 | for(i=0; i < info->port_count ; i++) { | 2419 | for(i=0; i < info->port_count ; i++) { |
| 2394 | struct slgt_info *port = info->port_array[i]; | 2420 | struct slgt_info *port = info->port_array[i]; |
| 2395 | 2421 | if (port == NULL) | |
| 2396 | if (port && (port->port.count || port->netcount) && | 2422 | continue; |
| 2423 | spin_lock(&port->lock); | ||
| 2424 | if ((port->port.count || port->netcount) && | ||
| 2397 | port->pending_bh && !port->bh_running && | 2425 | port->pending_bh && !port->bh_running && |
| 2398 | !port->bh_requested) { | 2426 | !port->bh_requested) { |
| 2399 | DBGISR(("%s bh queued\n", port->device_name)); | 2427 | DBGISR(("%s bh queued\n", port->device_name)); |
| 2400 | schedule_work(&port->task); | 2428 | schedule_work(&port->task); |
| 2401 | port->bh_requested = true; | 2429 | port->bh_requested = true; |
| 2402 | } | 2430 | } |
| 2431 | spin_unlock(&port->lock); | ||
| 2403 | } | 2432 | } |
| 2404 | 2433 | ||
| 2405 | spin_unlock(&info->lock); | ||
| 2406 | |||
| 2407 | DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); | 2434 | DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); |
| 2408 | return IRQ_HANDLED; | 2435 | return IRQ_HANDLED; |
| 2409 | } | 2436 | } |
| @@ -2883,6 +2910,69 @@ static int set_interface(struct slgt_info *info, int if_mode) | |||
| 2883 | return 0; | 2910 | return 0; |
| 2884 | } | 2911 | } |
| 2885 | 2912 | ||
| 2913 | static int get_xsync(struct slgt_info *info, int __user *xsync) | ||
| 2914 | { | ||
| 2915 | DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync)); | ||
| 2916 | if (put_user(info->xsync, xsync)) | ||
| 2917 | return -EFAULT; | ||
| 2918 | return 0; | ||
| 2919 | } | ||
| 2920 | |||
| 2921 | /* | ||
| 2922 | * set extended sync pattern (1 to 4 bytes) for extended sync mode | ||
| 2923 | * | ||
| 2924 | * sync pattern is contained in least significant bytes of value | ||
| 2925 | * most significant byte of sync pattern is oldest (1st sent/detected) | ||
| 2926 | */ | ||
| 2927 | static int set_xsync(struct slgt_info *info, int xsync) | ||
| 2928 | { | ||
| 2929 | unsigned long flags; | ||
| 2930 | |||
| 2931 | DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync)); | ||
| 2932 | spin_lock_irqsave(&info->lock, flags); | ||
| 2933 | info->xsync = xsync; | ||
| 2934 | wr_reg32(info, XSR, xsync); | ||
| 2935 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2936 | return 0; | ||
| 2937 | } | ||
| 2938 | |||
| 2939 | static int get_xctrl(struct slgt_info *info, int __user *xctrl) | ||
| 2940 | { | ||
| 2941 | DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl)); | ||
| 2942 | if (put_user(info->xctrl, xctrl)) | ||
| 2943 | return -EFAULT; | ||
| 2944 | return 0; | ||
| 2945 | } | ||
| 2946 | |||
| 2947 | /* | ||
| 2948 | * set extended control options | ||
| 2949 | * | ||
| 2950 | * xctrl[31:19] reserved, must be zero | ||
| 2951 | * xctrl[18:17] extended sync pattern length in bytes | ||
| 2952 | * 00 = 1 byte in xsr[7:0] | ||
| 2953 | * 01 = 2 bytes in xsr[15:0] | ||
| 2954 | * 10 = 3 bytes in xsr[23:0] | ||
| 2955 | * 11 = 4 bytes in xsr[31:0] | ||
| 2956 | * xctrl[16] 1 = enable terminal count, 0=disabled | ||
| 2957 | * xctrl[15:0] receive terminal count for fixed length packets | ||
| 2958 | * value is count minus one (0 = 1 byte packet) | ||
| 2959 | * when terminal count is reached, receiver | ||
| 2960 | * automatically returns to hunt mode and receive | ||
| 2961 | * FIFO contents are flushed to DMA buffers with | ||
| 2962 | * end of frame (EOF) status | ||
| 2963 | */ | ||
| 2964 | static int set_xctrl(struct slgt_info *info, int xctrl) | ||
| 2965 | { | ||
| 2966 | unsigned long flags; | ||
| 2967 | |||
| 2968 | DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl)); | ||
| 2969 | spin_lock_irqsave(&info->lock, flags); | ||
| 2970 | info->xctrl = xctrl; | ||
| 2971 | wr_reg32(info, XCR, xctrl); | ||
| 2972 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2973 | return 0; | ||
| 2974 | } | ||
| 2975 | |||
| 2886 | /* | 2976 | /* |
| 2887 | * set general purpose IO pin state and direction | 2977 | * set general purpose IO pin state and direction |
| 2888 | * | 2978 | * |
| @@ -2906,7 +2996,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
| 2906 | info->device_name, gpio.state, gpio.smask, | 2996 | info->device_name, gpio.state, gpio.smask, |
| 2907 | gpio.dir, gpio.dmask)); | 2997 | gpio.dir, gpio.dmask)); |
| 2908 | 2998 | ||
| 2909 | spin_lock_irqsave(&info->lock,flags); | 2999 | spin_lock_irqsave(&info->port_array[0]->lock, flags); |
| 2910 | if (gpio.dmask) { | 3000 | if (gpio.dmask) { |
| 2911 | data = rd_reg32(info, IODR); | 3001 | data = rd_reg32(info, IODR); |
| 2912 | data |= gpio.dmask & gpio.dir; | 3002 | data |= gpio.dmask & gpio.dir; |
| @@ -2919,7 +3009,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
| 2919 | data &= ~(gpio.smask & ~gpio.state); | 3009 | data &= ~(gpio.smask & ~gpio.state); |
| 2920 | wr_reg32(info, IOVR, data); | 3010 | wr_reg32(info, IOVR, data); |
| 2921 | } | 3011 | } |
| 2922 | spin_unlock_irqrestore(&info->lock,flags); | 3012 | spin_unlock_irqrestore(&info->port_array[0]->lock, flags); |
| 2923 | 3013 | ||
| 2924 | return 0; | 3014 | return 0; |
| 2925 | } | 3015 | } |
| @@ -3020,7 +3110,7 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
| 3020 | return -EINVAL; | 3110 | return -EINVAL; |
| 3021 | init_cond_wait(&wait, gpio.smask); | 3111 | init_cond_wait(&wait, gpio.smask); |
| 3022 | 3112 | ||
| 3023 | spin_lock_irqsave(&info->lock, flags); | 3113 | spin_lock_irqsave(&info->port_array[0]->lock, flags); |
| 3024 | /* enable interrupts for watched pins */ | 3114 | /* enable interrupts for watched pins */ |
| 3025 | wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); | 3115 | wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); |
| 3026 | /* get current pin states */ | 3116 | /* get current pin states */ |
| @@ -3032,20 +3122,20 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | |||
| 3032 | } else { | 3122 | } else { |
| 3033 | /* wait for target state */ | 3123 | /* wait for target state */ |
| 3034 | add_cond_wait(&info->gpio_wait_q, &wait); | 3124 | add_cond_wait(&info->gpio_wait_q, &wait); |
| 3035 | spin_unlock_irqrestore(&info->lock, flags); | 3125 | spin_unlock_irqrestore(&info->port_array[0]->lock, flags); |
| 3036 | schedule(); | 3126 | schedule(); |
| 3037 | if (signal_pending(current)) | 3127 | if (signal_pending(current)) |
| 3038 | rc = -ERESTARTSYS; | 3128 | rc = -ERESTARTSYS; |
| 3039 | else | 3129 | else |
| 3040 | gpio.state = wait.data; | 3130 | gpio.state = wait.data; |
| 3041 | spin_lock_irqsave(&info->lock, flags); | 3131 | spin_lock_irqsave(&info->port_array[0]->lock, flags); |
| 3042 | remove_cond_wait(&info->gpio_wait_q, &wait); | 3132 | remove_cond_wait(&info->gpio_wait_q, &wait); |
| 3043 | } | 3133 | } |
| 3044 | 3134 | ||
| 3045 | /* disable all GPIO interrupts if no waiting processes */ | 3135 | /* disable all GPIO interrupts if no waiting processes */ |
| 3046 | if (info->gpio_wait_q == NULL) | 3136 | if (info->gpio_wait_q == NULL) |
| 3047 | wr_reg32(info, IOER, 0); | 3137 | wr_reg32(info, IOER, 0); |
| 3048 | spin_unlock_irqrestore(&info->lock,flags); | 3138 | spin_unlock_irqrestore(&info->port_array[0]->lock, flags); |
| 3049 | 3139 | ||
| 3050 | if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) | 3140 | if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) |
| 3051 | rc = -EFAULT; | 3141 | rc = -EFAULT; |
| @@ -3578,7 +3668,6 @@ static void device_init(int adapter_num, struct pci_dev *pdev) | |||
| 3578 | 3668 | ||
| 3579 | /* copy resource information from first port to others */ | 3669 | /* copy resource information from first port to others */ |
| 3580 | for (i = 1; i < port_count; ++i) { | 3670 | for (i = 1; i < port_count; ++i) { |
| 3581 | port_array[i]->lock = port_array[0]->lock; | ||
| 3582 | port_array[i]->irq_level = port_array[0]->irq_level; | 3671 | port_array[i]->irq_level = port_array[0]->irq_level; |
| 3583 | port_array[i]->reg_addr = port_array[0]->reg_addr; | 3672 | port_array[i]->reg_addr = port_array[0]->reg_addr; |
| 3584 | alloc_dma_bufs(port_array[i]); | 3673 | alloc_dma_bufs(port_array[i]); |
| @@ -3763,7 +3852,9 @@ module_exit(slgt_exit); | |||
| 3763 | #define CALC_REGADDR() \ | 3852 | #define CALC_REGADDR() \ |
| 3764 | unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ | 3853 | unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ |
| 3765 | if (addr >= 0x80) \ | 3854 | if (addr >= 0x80) \ |
| 3766 | reg_addr += (info->port_num) * 32; | 3855 | reg_addr += (info->port_num) * 32; \ |
| 3856 | else if (addr >= 0x40) \ | ||
| 3857 | reg_addr += (info->port_num) * 16; | ||
| 3767 | 3858 | ||
| 3768 | static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) | 3859 | static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) |
| 3769 | { | 3860 | { |
| @@ -4182,7 +4273,13 @@ static void sync_mode(struct slgt_info *info) | |||
| 4182 | 4273 | ||
| 4183 | /* TCR (tx control) | 4274 | /* TCR (tx control) |
| 4184 | * | 4275 | * |
| 4185 | * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync | 4276 | * 15..13 mode |
| 4277 | * 000=HDLC/SDLC | ||
| 4278 | * 001=raw bit synchronous | ||
| 4279 | * 010=asynchronous/isochronous | ||
| 4280 | * 011=monosync byte synchronous | ||
| 4281 | * 100=bisync byte synchronous | ||
| 4282 | * 101=xsync byte synchronous | ||
| 4186 | * 12..10 encoding | 4283 | * 12..10 encoding |
| 4187 | * 09 CRC enable | 4284 | * 09 CRC enable |
| 4188 | * 08 CRC32 | 4285 | * 08 CRC32 |
| @@ -4197,6 +4294,9 @@ static void sync_mode(struct slgt_info *info) | |||
| 4197 | val = BIT2; | 4294 | val = BIT2; |
| 4198 | 4295 | ||
| 4199 | switch(info->params.mode) { | 4296 | switch(info->params.mode) { |
| 4297 | case MGSL_MODE_XSYNC: | ||
| 4298 | val |= BIT15 + BIT13; | ||
| 4299 | break; | ||
| 4200 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; | 4300 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; |
| 4201 | case MGSL_MODE_BISYNC: val |= BIT15; break; | 4301 | case MGSL_MODE_BISYNC: val |= BIT15; break; |
| 4202 | case MGSL_MODE_RAW: val |= BIT13; break; | 4302 | case MGSL_MODE_RAW: val |= BIT13; break; |
| @@ -4251,7 +4351,13 @@ static void sync_mode(struct slgt_info *info) | |||
| 4251 | 4351 | ||
| 4252 | /* RCR (rx control) | 4352 | /* RCR (rx control) |
| 4253 | * | 4353 | * |
| 4254 | * 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync | 4354 | * 15..13 mode |
| 4355 | * 000=HDLC/SDLC | ||
| 4356 | * 001=raw bit synchronous | ||
| 4357 | * 010=asynchronous/isochronous | ||
| 4358 | * 011=monosync byte synchronous | ||
| 4359 | * 100=bisync byte synchronous | ||
| 4360 | * 101=xsync byte synchronous | ||
| 4255 | * 12..10 encoding | 4361 | * 12..10 encoding |
| 4256 | * 09 CRC enable | 4362 | * 09 CRC enable |
| 4257 | * 08 CRC32 | 4363 | * 08 CRC32 |
| @@ -4263,6 +4369,9 @@ static void sync_mode(struct slgt_info *info) | |||
| 4263 | val = 0; | 4369 | val = 0; |
| 4264 | 4370 | ||
| 4265 | switch(info->params.mode) { | 4371 | switch(info->params.mode) { |
| 4372 | case MGSL_MODE_XSYNC: | ||
| 4373 | val |= BIT15 + BIT13; | ||
| 4374 | break; | ||
| 4266 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; | 4375 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; |
| 4267 | case MGSL_MODE_BISYNC: val |= BIT15; break; | 4376 | case MGSL_MODE_BISYNC: val |= BIT15; break; |
| 4268 | case MGSL_MODE_RAW: val |= BIT13; break; | 4377 | case MGSL_MODE_RAW: val |= BIT13; break; |
| @@ -4679,6 +4788,7 @@ static bool rx_get_buf(struct slgt_info *info) | |||
| 4679 | switch(info->params.mode) { | 4788 | switch(info->params.mode) { |
| 4680 | case MGSL_MODE_MONOSYNC: | 4789 | case MGSL_MODE_MONOSYNC: |
| 4681 | case MGSL_MODE_BISYNC: | 4790 | case MGSL_MODE_BISYNC: |
| 4791 | case MGSL_MODE_XSYNC: | ||
| 4682 | /* ignore residue in byte synchronous modes */ | 4792 | /* ignore residue in byte synchronous modes */ |
| 4683 | if (desc_residue(info->rbufs[i])) | 4793 | if (desc_residue(info->rbufs[i])) |
| 4684 | count--; | 4794 | count--; |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 38df8c19e74c..6b68a0fb4611 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
| @@ -503,6 +503,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 503 | struct kbd_struct * kbd; | 503 | struct kbd_struct * kbd; |
| 504 | unsigned int console; | 504 | unsigned int console; |
| 505 | unsigned char ucval; | 505 | unsigned char ucval; |
| 506 | unsigned int uival; | ||
| 506 | void __user *up = (void __user *)arg; | 507 | void __user *up = (void __user *)arg; |
| 507 | int i, perm; | 508 | int i, perm; |
| 508 | int ret = 0; | 509 | int ret = 0; |
| @@ -657,7 +658,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 657 | break; | 658 | break; |
| 658 | 659 | ||
| 659 | case KDGETMODE: | 660 | case KDGETMODE: |
| 660 | ucval = vc->vc_mode; | 661 | uival = vc->vc_mode; |
| 661 | goto setint; | 662 | goto setint; |
| 662 | 663 | ||
| 663 | case KDMAPDISP: | 664 | case KDMAPDISP: |
| @@ -695,7 +696,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 695 | break; | 696 | break; |
| 696 | 697 | ||
| 697 | case KDGKBMODE: | 698 | case KDGKBMODE: |
| 698 | ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : | 699 | uival = ((kbd->kbdmode == VC_RAW) ? K_RAW : |
| 699 | (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : | 700 | (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : |
| 700 | (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : | 701 | (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : |
| 701 | K_XLATE); | 702 | K_XLATE); |
| @@ -717,9 +718,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 717 | break; | 718 | break; |
| 718 | 719 | ||
| 719 | case KDGKBMETA: | 720 | case KDGKBMETA: |
| 720 | ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); | 721 | uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); |
| 721 | setint: | 722 | setint: |
| 722 | ret = put_user(ucval, (int __user *)arg); | 723 | ret = put_user(uival, (int __user *)arg); |
| 723 | break; | 724 | break; |
| 724 | 725 | ||
| 725 | case KDGETKEYCODE: | 726 | case KDGETKEYCODE: |
| @@ -949,7 +950,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
| 949 | for (i = 0; i < MAX_NR_CONSOLES; ++i) | 950 | for (i = 0; i < MAX_NR_CONSOLES; ++i) |
| 950 | if (! VT_IS_IN_USE(i)) | 951 | if (! VT_IS_IN_USE(i)) |
| 951 | break; | 952 | break; |
| 952 | ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; | 953 | uival = i < MAX_NR_CONSOLES ? (i+1) : -1; |
| 953 | goto setint; | 954 | goto setint; |
| 954 | 955 | ||
| 955 | /* | 956 | /* |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b3d22d659990..e28e41668177 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #include <linux/string.h> | 2 | #include <linux/string.h> |
| 3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
| 4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
| 5 | #include <linux/ctype.h> | ||
| 5 | #include <linux/dmi.h> | 6 | #include <linux/dmi.h> |
| 6 | #include <linux/efi.h> | 7 | #include <linux/efi.h> |
| 7 | #include <linux/bootmem.h> | 8 | #include <linux/bootmem.h> |
| @@ -361,6 +362,33 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy) | |||
| 361 | } | 362 | } |
| 362 | } | 363 | } |
| 363 | 364 | ||
| 365 | static void __init print_filtered(const char *info) | ||
| 366 | { | ||
| 367 | const char *p; | ||
| 368 | |||
| 369 | if (!info) | ||
| 370 | return; | ||
| 371 | |||
| 372 | for (p = info; *p; p++) | ||
| 373 | if (isprint(*p)) | ||
| 374 | printk(KERN_CONT "%c", *p); | ||
| 375 | else | ||
| 376 | printk(KERN_CONT "\\x%02x", *p & 0xff); | ||
| 377 | } | ||
| 378 | |||
| 379 | static void __init dmi_dump_ids(void) | ||
| 380 | { | ||
| 381 | printk(KERN_DEBUG "DMI: "); | ||
| 382 | print_filtered(dmi_get_system_info(DMI_BOARD_NAME)); | ||
| 383 | printk(KERN_CONT "/"); | ||
| 384 | print_filtered(dmi_get_system_info(DMI_PRODUCT_NAME)); | ||
| 385 | printk(KERN_CONT ", BIOS "); | ||
| 386 | print_filtered(dmi_get_system_info(DMI_BIOS_VERSION)); | ||
| 387 | printk(KERN_CONT " "); | ||
| 388 | print_filtered(dmi_get_system_info(DMI_BIOS_DATE)); | ||
| 389 | printk(KERN_CONT "\n"); | ||
| 390 | } | ||
| 391 | |||
| 364 | static int __init dmi_present(const char __iomem *p) | 392 | static int __init dmi_present(const char __iomem *p) |
| 365 | { | 393 | { |
| 366 | u8 buf[15]; | 394 | u8 buf[15]; |
| @@ -381,8 +409,10 @@ static int __init dmi_present(const char __iomem *p) | |||
| 381 | buf[14] >> 4, buf[14] & 0xF); | 409 | buf[14] >> 4, buf[14] & 0xF); |
| 382 | else | 410 | else |
| 383 | printk(KERN_INFO "DMI present.\n"); | 411 | printk(KERN_INFO "DMI present.\n"); |
| 384 | if (dmi_walk_early(dmi_decode) == 0) | 412 | if (dmi_walk_early(dmi_decode) == 0) { |
| 413 | dmi_dump_ids(); | ||
| 385 | return 0; | 414 | return 0; |
| 415 | } | ||
| 386 | } | 416 | } |
| 387 | return 1; | 417 | return 1; |
| 388 | } | 418 | } |
diff --git a/drivers/gpio/74x164.c b/drivers/gpio/74x164.c new file mode 100644 index 000000000000..d91ff4c282e9 --- /dev/null +++ b/drivers/gpio/74x164.c | |||
| @@ -0,0 +1,182 @@ | |||
| 1 | /* | ||
| 2 | * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> | ||
| 5 | * Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/mutex.h> | ||
| 14 | #include <linux/spi/spi.h> | ||
| 15 | #include <linux/spi/74x164.h> | ||
| 16 | #include <linux/gpio.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | |||
| 19 | #define GEN_74X164_GPIO_COUNT 8 | ||
| 20 | |||
| 21 | |||
| 22 | struct gen_74x164_chip { | ||
| 23 | struct spi_device *spi; | ||
| 24 | struct gpio_chip gpio_chip; | ||
| 25 | struct mutex lock; | ||
| 26 | u8 port_config; | ||
| 27 | }; | ||
| 28 | |||
| 29 | static void gen_74x164_set_value(struct gpio_chip *, unsigned, int); | ||
| 30 | |||
| 31 | static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc) | ||
| 32 | { | ||
| 33 | return container_of(gc, struct gen_74x164_chip, gpio_chip); | ||
| 34 | } | ||
| 35 | |||
| 36 | static int __gen_74x164_write_config(struct gen_74x164_chip *chip) | ||
| 37 | { | ||
| 38 | return spi_write(chip->spi, | ||
| 39 | &chip->port_config, sizeof(chip->port_config)); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int gen_74x164_direction_output(struct gpio_chip *gc, | ||
| 43 | unsigned offset, int val) | ||
| 44 | { | ||
| 45 | gen_74x164_set_value(gc, offset, val); | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset) | ||
| 50 | { | ||
| 51 | struct gen_74x164_chip *chip = gpio_to_chip(gc); | ||
| 52 | int ret; | ||
| 53 | |||
| 54 | mutex_lock(&chip->lock); | ||
| 55 | ret = (chip->port_config >> offset) & 0x1; | ||
| 56 | mutex_unlock(&chip->lock); | ||
| 57 | |||
| 58 | return ret; | ||
| 59 | } | ||
| 60 | |||
| 61 | static void gen_74x164_set_value(struct gpio_chip *gc, | ||
| 62 | unsigned offset, int val) | ||
| 63 | { | ||
| 64 | struct gen_74x164_chip *chip = gpio_to_chip(gc); | ||
| 65 | |||
| 66 | mutex_lock(&chip->lock); | ||
| 67 | if (val) | ||
| 68 | chip->port_config |= (1 << offset); | ||
| 69 | else | ||
| 70 | chip->port_config &= ~(1 << offset); | ||
| 71 | |||
| 72 | __gen_74x164_write_config(chip); | ||
| 73 | mutex_unlock(&chip->lock); | ||
| 74 | } | ||
| 75 | |||
| 76 | static int __devinit gen_74x164_probe(struct spi_device *spi) | ||
| 77 | { | ||
| 78 | struct gen_74x164_chip *chip; | ||
| 79 | struct gen_74x164_chip_platform_data *pdata; | ||
| 80 | int ret; | ||
| 81 | |||
| 82 | pdata = spi->dev.platform_data; | ||
| 83 | if (!pdata || !pdata->base) { | ||
| 84 | dev_dbg(&spi->dev, "incorrect or missing platform data\n"); | ||
| 85 | return -EINVAL; | ||
| 86 | } | ||
| 87 | |||
| 88 | /* | ||
| 89 | * bits_per_word cannot be configured in platform data | ||
| 90 | */ | ||
| 91 | spi->bits_per_word = 8; | ||
| 92 | |||
| 93 | ret = spi_setup(spi); | ||
| 94 | if (ret < 0) | ||
| 95 | return ret; | ||
| 96 | |||
| 97 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
| 98 | if (!chip) | ||
| 99 | return -ENOMEM; | ||
| 100 | |||
| 101 | mutex_init(&chip->lock); | ||
| 102 | |||
| 103 | dev_set_drvdata(&spi->dev, chip); | ||
| 104 | |||
| 105 | chip->spi = spi; | ||
| 106 | |||
| 107 | chip->gpio_chip.label = GEN_74X164_DRIVER_NAME, | ||
| 108 | chip->gpio_chip.direction_output = gen_74x164_direction_output; | ||
| 109 | chip->gpio_chip.get = gen_74x164_get_value; | ||
| 110 | chip->gpio_chip.set = gen_74x164_set_value; | ||
| 111 | chip->gpio_chip.base = pdata->base; | ||
| 112 | chip->gpio_chip.ngpio = GEN_74X164_GPIO_COUNT; | ||
| 113 | chip->gpio_chip.can_sleep = 1; | ||
| 114 | chip->gpio_chip.dev = &spi->dev; | ||
| 115 | chip->gpio_chip.owner = THIS_MODULE; | ||
| 116 | |||
| 117 | ret = __gen_74x164_write_config(chip); | ||
| 118 | if (ret) { | ||
| 119 | dev_err(&spi->dev, "Failed writing: %d\n", ret); | ||
| 120 | goto exit_destroy; | ||
| 121 | } | ||
| 122 | |||
| 123 | ret = gpiochip_add(&chip->gpio_chip); | ||
| 124 | if (ret) | ||
| 125 | goto exit_destroy; | ||
| 126 | |||
| 127 | return ret; | ||
| 128 | |||
| 129 | exit_destroy: | ||
| 130 | dev_set_drvdata(&spi->dev, NULL); | ||
| 131 | mutex_destroy(&chip->lock); | ||
| 132 | kfree(chip); | ||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int gen_74x164_remove(struct spi_device *spi) | ||
| 137 | { | ||
| 138 | struct gen_74x164_chip *chip; | ||
| 139 | int ret; | ||
| 140 | |||
| 141 | chip = dev_get_drvdata(&spi->dev); | ||
| 142 | if (chip == NULL) | ||
| 143 | return -ENODEV; | ||
| 144 | |||
| 145 | dev_set_drvdata(&spi->dev, NULL); | ||
| 146 | |||
| 147 | ret = gpiochip_remove(&chip->gpio_chip); | ||
| 148 | if (!ret) { | ||
| 149 | mutex_destroy(&chip->lock); | ||
| 150 | kfree(chip); | ||
| 151 | } else | ||
| 152 | dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", | ||
| 153 | ret); | ||
| 154 | |||
| 155 | return ret; | ||
| 156 | } | ||
| 157 | |||
| 158 | static struct spi_driver gen_74x164_driver = { | ||
| 159 | .driver = { | ||
| 160 | .name = GEN_74X164_DRIVER_NAME, | ||
| 161 | .owner = THIS_MODULE, | ||
| 162 | }, | ||
| 163 | .probe = gen_74x164_probe, | ||
| 164 | .remove = __devexit_p(gen_74x164_remove), | ||
| 165 | }; | ||
| 166 | |||
| 167 | static int __init gen_74x164_init(void) | ||
| 168 | { | ||
| 169 | return spi_register_driver(&gen_74x164_driver); | ||
| 170 | } | ||
| 171 | subsys_initcall(gen_74x164_init); | ||
| 172 | |||
| 173 | static void __exit gen_74x164_exit(void) | ||
| 174 | { | ||
| 175 | spi_unregister_driver(&gen_74x164_driver); | ||
| 176 | } | ||
| 177 | module_exit(gen_74x164_exit); | ||
| 178 | |||
| 179 | MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); | ||
| 180 | MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>"); | ||
| 181 | MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register"); | ||
| 182 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 510aa2054544..dd9b4ba8d32d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -70,6 +70,11 @@ config GPIO_MAX730X | |||
| 70 | 70 | ||
| 71 | comment "Memory mapped GPIO expanders:" | 71 | comment "Memory mapped GPIO expanders:" |
| 72 | 72 | ||
| 73 | config GPIO_BASIC_MMIO | ||
| 74 | tristate "Basic memory-mapped GPIO controllers support" | ||
| 75 | help | ||
| 76 | Say yes here to support basic memory-mapped GPIO controllers. | ||
| 77 | |||
| 73 | config GPIO_IT8761E | 78 | config GPIO_IT8761E |
| 74 | tristate "IT8761E GPIO support" | 79 | tristate "IT8761E GPIO support" |
| 75 | depends on GPIOLIB | 80 | depends on GPIOLIB |
| @@ -267,6 +272,13 @@ config GPIO_ADP5588 | |||
| 267 | To compile this driver as a module, choose M here: the module will be | 272 | To compile this driver as a module, choose M here: the module will be |
| 268 | called adp5588-gpio. | 273 | called adp5588-gpio. |
| 269 | 274 | ||
| 275 | config GPIO_ADP5588_IRQ | ||
| 276 | bool "Interrupt controller support for ADP5588" | ||
| 277 | depends on GPIO_ADP5588=y | ||
| 278 | help | ||
| 279 | Say yes here to enable the adp5588 to be used as an interrupt | ||
| 280 | controller. It requires the driver to be built in the kernel. | ||
| 281 | |||
| 270 | comment "PCI GPIO expanders:" | 282 | comment "PCI GPIO expanders:" |
| 271 | 283 | ||
| 272 | config GPIO_CS5535 | 284 | config GPIO_CS5535 |
| @@ -301,6 +313,14 @@ config GPIO_LANGWELL | |||
| 301 | help | 313 | help |
| 302 | Say Y here to support Intel Langwell/Penwell GPIO. | 314 | Say Y here to support Intel Langwell/Penwell GPIO. |
| 303 | 315 | ||
| 316 | config GPIO_PCH | ||
| 317 | tristate "PCH GPIO of Intel Topcliff" | ||
| 318 | depends on PCI | ||
| 319 | help | ||
| 320 | This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff | ||
| 321 | which is an IOH(Input/Output Hub) for x86 embedded processor. | ||
| 322 | This driver can access PCH GPIO device. | ||
| 323 | |||
| 304 | config GPIO_TIMBERDALE | 324 | config GPIO_TIMBERDALE |
| 305 | bool "Support for timberdale GPIO IP" | 325 | bool "Support for timberdale GPIO IP" |
| 306 | depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM | 326 | depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM |
| @@ -339,6 +359,14 @@ config GPIO_MC33880 | |||
| 339 | SPI driver for Freescale MC33880 high-side/low-side switch. | 359 | SPI driver for Freescale MC33880 high-side/low-side switch. |
| 340 | This provides GPIO interface supporting inputs and outputs. | 360 | This provides GPIO interface supporting inputs and outputs. |
| 341 | 361 | ||
| 362 | config GPIO_74X164 | ||
| 363 | tristate "74x164 serial-in/parallel-out 8-bits shift register" | ||
| 364 | depends on SPI_MASTER | ||
| 365 | help | ||
| 366 | Platform driver for 74x164 compatible serial-in/parallel-out | ||
| 367 | 8-outputs shift registers. This driver can be used to provide access | ||
| 368 | to more gpio outputs. | ||
| 369 | |||
| 342 | comment "AC97 GPIO expanders:" | 370 | comment "AC97 GPIO expanders:" |
| 343 | 371 | ||
| 344 | config GPIO_UCB1400 | 372 | config GPIO_UCB1400 |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fc6019d93720..da2ecde5abdd 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -10,6 +10,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o | |||
| 10 | 10 | ||
| 11 | obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o | 11 | obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o |
| 12 | obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o | 12 | obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o |
| 13 | obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o | ||
| 13 | obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o | 14 | obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o |
| 14 | obj-$(CONFIG_GPIO_MAX730X) += max730x.o | 15 | obj-$(CONFIG_GPIO_MAX730X) += max730x.o |
| 15 | obj-$(CONFIG_GPIO_MAX7300) += max7300.o | 16 | obj-$(CONFIG_GPIO_MAX7300) += max7300.o |
| @@ -17,8 +18,10 @@ obj-$(CONFIG_GPIO_MAX7301) += max7301.o | |||
| 17 | obj-$(CONFIG_GPIO_MAX732X) += max732x.o | 18 | obj-$(CONFIG_GPIO_MAX732X) += max732x.o |
| 18 | obj-$(CONFIG_GPIO_MC33880) += mc33880.o | 19 | obj-$(CONFIG_GPIO_MC33880) += mc33880.o |
| 19 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | 20 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o |
| 21 | obj-$(CONFIG_GPIO_74X164) += 74x164.o | ||
| 20 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 22 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
| 21 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 23 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
| 24 | obj-$(CONFIG_GPIO_PCH) += pch_gpio.o | ||
| 22 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 25 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
| 23 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o | 26 | obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o |
| 24 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o | 27 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o |
diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/adp5588-gpio.c index 2e8e9e24f887..0871f78af593 100644 --- a/drivers/gpio/adp5588-gpio.c +++ b/drivers/gpio/adp5588-gpio.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * GPIO Chip driver for Analog Devices | 2 | * GPIO Chip driver for Analog Devices |
| 3 | * ADP5588 I/O Expander and QWERTY Keypad Controller | 3 | * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller |
| 4 | * | 4 | * |
| 5 | * Copyright 2009 Analog Devices Inc. | 5 | * Copyright 2009-2010 Analog Devices Inc. |
| 6 | * | 6 | * |
| 7 | * Licensed under the GPL-2 or later. | 7 | * Licensed under the GPL-2 or later. |
| 8 | */ | 8 | */ |
| @@ -13,21 +13,34 @@ | |||
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
| 15 | #include <linux/gpio.h> | 15 | #include <linux/gpio.h> |
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/irq.h> | ||
| 16 | 18 | ||
| 17 | #include <linux/i2c/adp5588.h> | 19 | #include <linux/i2c/adp5588.h> |
| 18 | 20 | ||
| 19 | #define DRV_NAME "adp5588-gpio" | 21 | #define DRV_NAME "adp5588-gpio" |
| 20 | #define MAXGPIO 18 | 22 | |
| 21 | #define ADP_BANK(offs) ((offs) >> 3) | 23 | /* |
| 22 | #define ADP_BIT(offs) (1u << ((offs) & 0x7)) | 24 | * Early pre 4.0 Silicon required to delay readout by at least 25ms, |
| 25 | * since the Event Counter Register updated 25ms after the interrupt | ||
| 26 | * asserted. | ||
| 27 | */ | ||
| 28 | #define WA_DELAYED_READOUT_REVID(rev) ((rev) < 4) | ||
| 23 | 29 | ||
| 24 | struct adp5588_gpio { | 30 | struct adp5588_gpio { |
| 25 | struct i2c_client *client; | 31 | struct i2c_client *client; |
| 26 | struct gpio_chip gpio_chip; | 32 | struct gpio_chip gpio_chip; |
| 27 | struct mutex lock; /* protect cached dir, dat_out */ | 33 | struct mutex lock; /* protect cached dir, dat_out */ |
| 34 | /* protect serialized access to the interrupt controller bus */ | ||
| 35 | struct mutex irq_lock; | ||
| 28 | unsigned gpio_start; | 36 | unsigned gpio_start; |
| 37 | unsigned irq_base; | ||
| 29 | uint8_t dat_out[3]; | 38 | uint8_t dat_out[3]; |
| 30 | uint8_t dir[3]; | 39 | uint8_t dir[3]; |
| 40 | uint8_t int_lvl[3]; | ||
| 41 | uint8_t int_en[3]; | ||
| 42 | uint8_t irq_mask[3]; | ||
| 43 | uint8_t irq_stat[3]; | ||
| 31 | }; | 44 | }; |
| 32 | 45 | ||
| 33 | static int adp5588_gpio_read(struct i2c_client *client, u8 reg) | 46 | static int adp5588_gpio_read(struct i2c_client *client, u8 reg) |
| @@ -55,8 +68,8 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) | |||
| 55 | struct adp5588_gpio *dev = | 68 | struct adp5588_gpio *dev = |
| 56 | container_of(chip, struct adp5588_gpio, gpio_chip); | 69 | container_of(chip, struct adp5588_gpio, gpio_chip); |
| 57 | 70 | ||
| 58 | return !!(adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + ADP_BANK(off)) | 71 | return !!(adp5588_gpio_read(dev->client, |
| 59 | & ADP_BIT(off)); | 72 | GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off)); |
| 60 | } | 73 | } |
| 61 | 74 | ||
| 62 | static void adp5588_gpio_set_value(struct gpio_chip *chip, | 75 | static void adp5588_gpio_set_value(struct gpio_chip *chip, |
| @@ -66,8 +79,8 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip, | |||
| 66 | struct adp5588_gpio *dev = | 79 | struct adp5588_gpio *dev = |
| 67 | container_of(chip, struct adp5588_gpio, gpio_chip); | 80 | container_of(chip, struct adp5588_gpio, gpio_chip); |
| 68 | 81 | ||
| 69 | bank = ADP_BANK(off); | 82 | bank = ADP5588_BANK(off); |
| 70 | bit = ADP_BIT(off); | 83 | bit = ADP5588_BIT(off); |
| 71 | 84 | ||
| 72 | mutex_lock(&dev->lock); | 85 | mutex_lock(&dev->lock); |
| 73 | if (val) | 86 | if (val) |
| @@ -87,10 +100,10 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) | |||
| 87 | struct adp5588_gpio *dev = | 100 | struct adp5588_gpio *dev = |
| 88 | container_of(chip, struct adp5588_gpio, gpio_chip); | 101 | container_of(chip, struct adp5588_gpio, gpio_chip); |
| 89 | 102 | ||
| 90 | bank = ADP_BANK(off); | 103 | bank = ADP5588_BANK(off); |
| 91 | 104 | ||
| 92 | mutex_lock(&dev->lock); | 105 | mutex_lock(&dev->lock); |
| 93 | dev->dir[bank] &= ~ADP_BIT(off); | 106 | dev->dir[bank] &= ~ADP5588_BIT(off); |
| 94 | ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]); | 107 | ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]); |
| 95 | mutex_unlock(&dev->lock); | 108 | mutex_unlock(&dev->lock); |
| 96 | 109 | ||
| @@ -105,8 +118,8 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, | |||
| 105 | struct adp5588_gpio *dev = | 118 | struct adp5588_gpio *dev = |
| 106 | container_of(chip, struct adp5588_gpio, gpio_chip); | 119 | container_of(chip, struct adp5588_gpio, gpio_chip); |
| 107 | 120 | ||
| 108 | bank = ADP_BANK(off); | 121 | bank = ADP5588_BANK(off); |
| 109 | bit = ADP_BIT(off); | 122 | bit = ADP5588_BIT(off); |
| 110 | 123 | ||
| 111 | mutex_lock(&dev->lock); | 124 | mutex_lock(&dev->lock); |
| 112 | dev->dir[bank] |= bit; | 125 | dev->dir[bank] |= bit; |
| @@ -125,6 +138,213 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, | |||
| 125 | return ret; | 138 | return ret; |
| 126 | } | 139 | } |
| 127 | 140 | ||
| 141 | #ifdef CONFIG_GPIO_ADP5588_IRQ | ||
| 142 | static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off) | ||
| 143 | { | ||
| 144 | struct adp5588_gpio *dev = | ||
| 145 | container_of(chip, struct adp5588_gpio, gpio_chip); | ||
| 146 | return dev->irq_base + off; | ||
| 147 | } | ||
| 148 | |||
| 149 | static void adp5588_irq_bus_lock(unsigned int irq) | ||
| 150 | { | ||
| 151 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | ||
| 152 | mutex_lock(&dev->irq_lock); | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | ||
| 156 | * genirq core code can issue chip->mask/unmask from atomic context. | ||
| 157 | * This doesn't work for slow busses where an access needs to sleep. | ||
| 158 | * bus_sync_unlock() is therefore called outside the atomic context, | ||
| 159 | * syncs the current irq mask state with the slow external controller | ||
| 160 | * and unlocks the bus. | ||
| 161 | */ | ||
| 162 | |||
| 163 | static void adp5588_irq_bus_sync_unlock(unsigned int irq) | ||
| 164 | { | ||
| 165 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | ||
| 166 | int i; | ||
| 167 | |||
| 168 | for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) | ||
| 169 | if (dev->int_en[i] ^ dev->irq_mask[i]) { | ||
| 170 | dev->int_en[i] = dev->irq_mask[i]; | ||
| 171 | adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i, | ||
| 172 | dev->int_en[i]); | ||
| 173 | } | ||
| 174 | |||
| 175 | mutex_unlock(&dev->irq_lock); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void adp5588_irq_mask(unsigned int irq) | ||
| 179 | { | ||
| 180 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | ||
| 181 | unsigned gpio = irq - dev->irq_base; | ||
| 182 | |||
| 183 | dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void adp5588_irq_unmask(unsigned int irq) | ||
| 187 | { | ||
| 188 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | ||
| 189 | unsigned gpio = irq - dev->irq_base; | ||
| 190 | |||
| 191 | dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio); | ||
| 192 | } | ||
| 193 | |||
| 194 | static int adp5588_irq_set_type(unsigned int irq, unsigned int type) | ||
| 195 | { | ||
| 196 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | ||
| 197 | uint16_t gpio = irq - dev->irq_base; | ||
| 198 | unsigned bank, bit; | ||
| 199 | |||
| 200 | if ((type & IRQ_TYPE_EDGE_BOTH)) { | ||
| 201 | dev_err(&dev->client->dev, "irq %d: unsupported type %d\n", | ||
| 202 | irq, type); | ||
| 203 | return -EINVAL; | ||
| 204 | } | ||
| 205 | |||
| 206 | bank = ADP5588_BANK(gpio); | ||
| 207 | bit = ADP5588_BIT(gpio); | ||
| 208 | |||
| 209 | if (type & IRQ_TYPE_LEVEL_HIGH) | ||
| 210 | dev->int_lvl[bank] |= bit; | ||
| 211 | else if (type & IRQ_TYPE_LEVEL_LOW) | ||
| 212 | dev->int_lvl[bank] &= ~bit; | ||
| 213 | else | ||
| 214 | return -EINVAL; | ||
| 215 | |||
| 216 | adp5588_gpio_direction_input(&dev->gpio_chip, gpio); | ||
| 217 | adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank, | ||
| 218 | dev->int_lvl[bank]); | ||
| 219 | |||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | static struct irq_chip adp5588_irq_chip = { | ||
| 224 | .name = "adp5588", | ||
| 225 | .mask = adp5588_irq_mask, | ||
| 226 | .unmask = adp5588_irq_unmask, | ||
| 227 | .bus_lock = adp5588_irq_bus_lock, | ||
| 228 | .bus_sync_unlock = adp5588_irq_bus_sync_unlock, | ||
| 229 | .set_type = adp5588_irq_set_type, | ||
| 230 | }; | ||
| 231 | |||
| 232 | static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf) | ||
| 233 | { | ||
| 234 | int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf); | ||
| 235 | |||
| 236 | if (ret < 0) | ||
| 237 | dev_err(&client->dev, "Read INT_STAT Error\n"); | ||
| 238 | |||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | |||
| 242 | static irqreturn_t adp5588_irq_handler(int irq, void *devid) | ||
| 243 | { | ||
| 244 | struct adp5588_gpio *dev = devid; | ||
| 245 | unsigned status, bank, bit, pending; | ||
| 246 | int ret; | ||
| 247 | status = adp5588_gpio_read(dev->client, INT_STAT); | ||
| 248 | |||
| 249 | if (status & ADP5588_GPI_INT) { | ||
| 250 | ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat); | ||
| 251 | if (ret < 0) | ||
| 252 | memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat)); | ||
| 253 | |||
| 254 | for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO); | ||
| 255 | bank++, bit = 0) { | ||
| 256 | pending = dev->irq_stat[bank] & dev->irq_mask[bank]; | ||
| 257 | |||
| 258 | while (pending) { | ||
| 259 | if (pending & (1 << bit)) { | ||
| 260 | handle_nested_irq(dev->irq_base + | ||
| 261 | (bank << 3) + bit); | ||
| 262 | pending &= ~(1 << bit); | ||
| 263 | |||
| 264 | } | ||
| 265 | bit++; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */ | ||
| 271 | |||
| 272 | return IRQ_HANDLED; | ||
| 273 | } | ||
| 274 | |||
| 275 | static int adp5588_irq_setup(struct adp5588_gpio *dev) | ||
| 276 | { | ||
| 277 | struct i2c_client *client = dev->client; | ||
| 278 | struct adp5588_gpio_platform_data *pdata = client->dev.platform_data; | ||
| 279 | unsigned gpio; | ||
| 280 | int ret; | ||
| 281 | |||
| 282 | adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC); | ||
| 283 | adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */ | ||
| 284 | adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */ | ||
| 285 | |||
| 286 | dev->irq_base = pdata->irq_base; | ||
| 287 | mutex_init(&dev->irq_lock); | ||
| 288 | |||
| 289 | for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) { | ||
| 290 | int irq = gpio + dev->irq_base; | ||
| 291 | set_irq_chip_data(irq, dev); | ||
| 292 | set_irq_chip_and_handler(irq, &adp5588_irq_chip, | ||
| 293 | handle_level_irq); | ||
| 294 | set_irq_nested_thread(irq, 1); | ||
| 295 | #ifdef CONFIG_ARM | ||
| 296 | /* | ||
| 297 | * ARM needs us to explicitly flag the IRQ as VALID, | ||
| 298 | * once we do so, it will also set the noprobe. | ||
| 299 | */ | ||
| 300 | set_irq_flags(irq, IRQF_VALID); | ||
| 301 | #else | ||
| 302 | set_irq_noprobe(irq); | ||
| 303 | #endif | ||
| 304 | } | ||
| 305 | |||
| 306 | ret = request_threaded_irq(client->irq, | ||
| 307 | NULL, | ||
| 308 | adp5588_irq_handler, | ||
| 309 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 310 | dev_name(&client->dev), dev); | ||
| 311 | if (ret) { | ||
| 312 | dev_err(&client->dev, "failed to request irq %d\n", | ||
| 313 | client->irq); | ||
| 314 | goto out; | ||
| 315 | } | ||
| 316 | |||
| 317 | dev->gpio_chip.to_irq = adp5588_gpio_to_irq; | ||
| 318 | adp5588_gpio_write(client, CFG, | ||
| 319 | ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT); | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | |||
| 323 | out: | ||
| 324 | dev->irq_base = 0; | ||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | static void adp5588_irq_teardown(struct adp5588_gpio *dev) | ||
| 329 | { | ||
| 330 | if (dev->irq_base) | ||
| 331 | free_irq(dev->client->irq, dev); | ||
| 332 | } | ||
| 333 | |||
| 334 | #else | ||
| 335 | static int adp5588_irq_setup(struct adp5588_gpio *dev) | ||
| 336 | { | ||
| 337 | struct i2c_client *client = dev->client; | ||
| 338 | dev_warn(&client->dev, "interrupt support not compiled in\n"); | ||
| 339 | |||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 343 | static void adp5588_irq_teardown(struct adp5588_gpio *dev) | ||
| 344 | { | ||
| 345 | } | ||
| 346 | #endif /* CONFIG_GPIO_ADP5588_IRQ */ | ||
| 347 | |||
| 128 | static int __devinit adp5588_gpio_probe(struct i2c_client *client, | 348 | static int __devinit adp5588_gpio_probe(struct i2c_client *client, |
| 129 | const struct i2c_device_id *id) | 349 | const struct i2c_device_id *id) |
| 130 | { | 350 | { |
| @@ -160,37 +380,46 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client, | |||
| 160 | gc->can_sleep = 1; | 380 | gc->can_sleep = 1; |
| 161 | 381 | ||
| 162 | gc->base = pdata->gpio_start; | 382 | gc->base = pdata->gpio_start; |
| 163 | gc->ngpio = MAXGPIO; | 383 | gc->ngpio = ADP5588_MAXGPIO; |
| 164 | gc->label = client->name; | 384 | gc->label = client->name; |
| 165 | gc->owner = THIS_MODULE; | 385 | gc->owner = THIS_MODULE; |
| 166 | 386 | ||
| 167 | mutex_init(&dev->lock); | 387 | mutex_init(&dev->lock); |
| 168 | 388 | ||
| 169 | |||
| 170 | ret = adp5588_gpio_read(dev->client, DEV_ID); | 389 | ret = adp5588_gpio_read(dev->client, DEV_ID); |
| 171 | if (ret < 0) | 390 | if (ret < 0) |
| 172 | goto err; | 391 | goto err; |
| 173 | 392 | ||
| 174 | revid = ret & ADP5588_DEVICE_ID_MASK; | 393 | revid = ret & ADP5588_DEVICE_ID_MASK; |
| 175 | 394 | ||
| 176 | for (i = 0, ret = 0; i <= ADP_BANK(MAXGPIO); i++) { | 395 | for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) { |
| 177 | dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i); | 396 | dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i); |
| 178 | dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i); | 397 | dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i); |
| 179 | ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0); | 398 | ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0); |
| 180 | ret |= adp5588_gpio_write(client, GPIO_PULL1 + i, | 399 | ret |= adp5588_gpio_write(client, GPIO_PULL1 + i, |
| 181 | (pdata->pullup_dis_mask >> (8 * i)) & 0xFF); | 400 | (pdata->pullup_dis_mask >> (8 * i)) & 0xFF); |
| 182 | 401 | ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0); | |
| 183 | if (ret) | 402 | if (ret) |
| 184 | goto err; | 403 | goto err; |
| 185 | } | 404 | } |
| 186 | 405 | ||
| 406 | if (pdata->irq_base) { | ||
| 407 | if (WA_DELAYED_READOUT_REVID(revid)) { | ||
| 408 | dev_warn(&client->dev, "GPIO int not supported\n"); | ||
| 409 | } else { | ||
| 410 | ret = adp5588_irq_setup(dev); | ||
| 411 | if (ret) | ||
| 412 | goto err; | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 187 | ret = gpiochip_add(&dev->gpio_chip); | 416 | ret = gpiochip_add(&dev->gpio_chip); |
| 188 | if (ret) | 417 | if (ret) |
| 189 | goto err; | 418 | goto err_irq; |
| 190 | 419 | ||
| 191 | dev_info(&client->dev, "gpios %d..%d on a %s Rev. %d\n", | 420 | dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n", |
| 192 | gc->base, gc->base + gc->ngpio - 1, | 421 | gc->base, gc->base + gc->ngpio - 1, |
| 193 | client->name, revid); | 422 | pdata->irq_base, client->name, revid); |
| 194 | 423 | ||
| 195 | if (pdata->setup) { | 424 | if (pdata->setup) { |
| 196 | ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); | 425 | ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); |
| @@ -199,8 +428,11 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client, | |||
| 199 | } | 428 | } |
| 200 | 429 | ||
| 201 | i2c_set_clientdata(client, dev); | 430 | i2c_set_clientdata(client, dev); |
| 431 | |||
| 202 | return 0; | 432 | return 0; |
| 203 | 433 | ||
| 434 | err_irq: | ||
| 435 | adp5588_irq_teardown(dev); | ||
| 204 | err: | 436 | err: |
| 205 | kfree(dev); | 437 | kfree(dev); |
| 206 | return ret; | 438 | return ret; |
| @@ -222,6 +454,9 @@ static int __devexit adp5588_gpio_remove(struct i2c_client *client) | |||
| 222 | } | 454 | } |
| 223 | } | 455 | } |
| 224 | 456 | ||
| 457 | if (dev->irq_base) | ||
| 458 | free_irq(dev->client->irq, dev); | ||
| 459 | |||
| 225 | ret = gpiochip_remove(&dev->gpio_chip); | 460 | ret = gpiochip_remove(&dev->gpio_chip); |
| 226 | if (ret) { | 461 | if (ret) { |
| 227 | dev_err(&client->dev, "gpiochip_remove failed %d\n", ret); | 462 | dev_err(&client->dev, "gpiochip_remove failed %d\n", ret); |
diff --git a/drivers/gpio/basic_mmio_gpio.c b/drivers/gpio/basic_mmio_gpio.c new file mode 100644 index 000000000000..3addea65894e --- /dev/null +++ b/drivers/gpio/basic_mmio_gpio.c | |||
| @@ -0,0 +1,297 @@ | |||
| 1 | /* | ||
| 2 | * Driver for basic memory-mapped GPIO controllers. | ||
| 3 | * | ||
| 4 | * Copyright 2008 MontaVista Software, Inc. | ||
| 5 | * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | * | ||
| 12 | * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... | ||
| 13 | * ...`` ```````.. | ||
| 14 | * ..The simplest form of a GPIO controller that the driver supports is`` | ||
| 15 | * `.just a single "data" register, where GPIO state can be read and/or ` | ||
| 16 | * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` | ||
| 17 | * ````````` | ||
| 18 | ___ | ||
| 19 | _/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... | ||
| 20 | __________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . | ||
| 21 | o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` | ||
| 22 | `....trivial..'~`.```.``` | ||
| 23 | * ``````` | ||
| 24 | * .```````~~~~`..`.``.``. | ||
| 25 | * . The driver supports `... ,..```.`~~~```````````````....````.``,, | ||
| 26 | * . big-endian notation, just`. .. A bit more sophisticated controllers , | ||
| 27 | * . register the device with -be`. .with a pair of set/clear-bit registers , | ||
| 28 | * `.. suffix. ```~~`````....`.` . affecting the data register and the .` | ||
| 29 | * ``.`.``...``` ```.. output pins are also supported.` | ||
| 30 | * ^^ `````.`````````.,``~``~``~~`````` | ||
| 31 | * . ^^ | ||
| 32 | * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. | ||
| 33 | * .. The expectation is that in at least some cases . ,-~~~-, | ||
| 34 | * .this will be used with roll-your-own ASIC/FPGA .` \ / | ||
| 35 | * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / | ||
| 36 | * ..````````......``````````` \o_ | ||
| 37 | * | | ||
| 38 | * ^^ / \ | ||
| 39 | * | ||
| 40 | * ...`````~~`.....``.`..........``````.`.``.```........``. | ||
| 41 | * ` 8, 16, 32 and 64 bits registers are supported, and``. | ||
| 42 | * . the number of GPIOs is determined by the width of ~ | ||
| 43 | * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ | ||
| 44 | * `.......````.``` | ||
| 45 | */ | ||
| 46 | |||
| 47 | #include <linux/init.h> | ||
| 48 | #include <linux/bug.h> | ||
| 49 | #include <linux/kernel.h> | ||
| 50 | #include <linux/module.h> | ||
| 51 | #include <linux/spinlock.h> | ||
| 52 | #include <linux/compiler.h> | ||
| 53 | #include <linux/types.h> | ||
| 54 | #include <linux/errno.h> | ||
| 55 | #include <linux/log2.h> | ||
| 56 | #include <linux/ioport.h> | ||
| 57 | #include <linux/io.h> | ||
| 58 | #include <linux/gpio.h> | ||
| 59 | #include <linux/slab.h> | ||
| 60 | #include <linux/platform_device.h> | ||
| 61 | #include <linux/mod_devicetable.h> | ||
| 62 | #include <linux/basic_mmio_gpio.h> | ||
| 63 | |||
| 64 | struct bgpio_chip { | ||
| 65 | struct gpio_chip gc; | ||
| 66 | void __iomem *reg_dat; | ||
| 67 | void __iomem *reg_set; | ||
| 68 | void __iomem *reg_clr; | ||
| 69 | |||
| 70 | /* Number of bits (GPIOs): <register width> * 8. */ | ||
| 71 | int bits; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Some GPIO controllers work with the big-endian bits notation, | ||
| 75 | * e.g. in a 8-bits register, GPIO7 is the least significant bit. | ||
| 76 | */ | ||
| 77 | int big_endian_bits; | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Used to lock bgpio_chip->data. Also, this is needed to keep | ||
| 81 | * shadowed and real data registers writes together. | ||
| 82 | */ | ||
| 83 | spinlock_t lock; | ||
| 84 | |||
| 85 | /* Shadowed data register to clear/set bits safely. */ | ||
| 86 | unsigned long data; | ||
| 87 | }; | ||
| 88 | |||
| 89 | static struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc) | ||
| 90 | { | ||
| 91 | return container_of(gc, struct bgpio_chip, gc); | ||
| 92 | } | ||
| 93 | |||
| 94 | static unsigned long bgpio_in(struct bgpio_chip *bgc) | ||
| 95 | { | ||
| 96 | switch (bgc->bits) { | ||
| 97 | case 8: | ||
| 98 | return __raw_readb(bgc->reg_dat); | ||
| 99 | case 16: | ||
| 100 | return __raw_readw(bgc->reg_dat); | ||
| 101 | case 32: | ||
| 102 | return __raw_readl(bgc->reg_dat); | ||
| 103 | #if BITS_PER_LONG >= 64 | ||
| 104 | case 64: | ||
| 105 | return __raw_readq(bgc->reg_dat); | ||
| 106 | #endif | ||
| 107 | } | ||
| 108 | return -EINVAL; | ||
| 109 | } | ||
| 110 | |||
| 111 | static void bgpio_out(struct bgpio_chip *bgc, void __iomem *reg, | ||
| 112 | unsigned long data) | ||
| 113 | { | ||
| 114 | switch (bgc->bits) { | ||
| 115 | case 8: | ||
| 116 | __raw_writeb(data, reg); | ||
| 117 | return; | ||
| 118 | case 16: | ||
| 119 | __raw_writew(data, reg); | ||
| 120 | return; | ||
| 121 | case 32: | ||
| 122 | __raw_writel(data, reg); | ||
| 123 | return; | ||
| 124 | #if BITS_PER_LONG >= 64 | ||
| 125 | case 64: | ||
| 126 | __raw_writeq(data, reg); | ||
| 127 | return; | ||
| 128 | #endif | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin) | ||
| 133 | { | ||
| 134 | if (bgc->big_endian_bits) | ||
| 135 | return 1 << (bgc->bits - 1 - pin); | ||
| 136 | else | ||
| 137 | return 1 << pin; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 141 | { | ||
| 142 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
| 143 | |||
| 144 | return bgpio_in(bgc) & bgpio_pin2mask(bgc, gpio); | ||
| 145 | } | ||
| 146 | |||
| 147 | static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 148 | { | ||
| 149 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
| 150 | unsigned long mask = bgpio_pin2mask(bgc, gpio); | ||
| 151 | unsigned long flags; | ||
| 152 | |||
| 153 | if (bgc->reg_set) { | ||
| 154 | if (val) | ||
| 155 | bgpio_out(bgc, bgc->reg_set, mask); | ||
| 156 | else | ||
| 157 | bgpio_out(bgc, bgc->reg_clr, mask); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | |||
| 161 | spin_lock_irqsave(&bgc->lock, flags); | ||
| 162 | |||
| 163 | if (val) | ||
| 164 | bgc->data |= mask; | ||
| 165 | else | ||
| 166 | bgc->data &= ~mask; | ||
| 167 | |||
| 168 | bgpio_out(bgc, bgc->reg_dat, bgc->data); | ||
| 169 | |||
| 170 | spin_unlock_irqrestore(&bgc->lock, flags); | ||
| 171 | } | ||
| 172 | |||
| 173 | static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
| 174 | { | ||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 179 | { | ||
| 180 | bgpio_set(gc, gpio, val); | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int __devinit bgpio_probe(struct platform_device *pdev) | ||
| 185 | { | ||
| 186 | const struct platform_device_id *platid = platform_get_device_id(pdev); | ||
| 187 | struct device *dev = &pdev->dev; | ||
| 188 | struct bgpio_pdata *pdata = dev_get_platdata(dev); | ||
| 189 | struct bgpio_chip *bgc; | ||
| 190 | struct resource *res_dat; | ||
| 191 | struct resource *res_set; | ||
| 192 | struct resource *res_clr; | ||
| 193 | resource_size_t dat_sz; | ||
| 194 | int bits; | ||
| 195 | int ret; | ||
| 196 | |||
| 197 | res_dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); | ||
| 198 | if (!res_dat) | ||
| 199 | return -EINVAL; | ||
| 200 | |||
| 201 | dat_sz = resource_size(res_dat); | ||
| 202 | if (!is_power_of_2(dat_sz)) | ||
| 203 | return -EINVAL; | ||
| 204 | |||
| 205 | bits = dat_sz * 8; | ||
| 206 | if (bits > BITS_PER_LONG) | ||
| 207 | return -EINVAL; | ||
| 208 | |||
| 209 | bgc = devm_kzalloc(dev, sizeof(*bgc), GFP_KERNEL); | ||
| 210 | if (!bgc) | ||
| 211 | return -ENOMEM; | ||
| 212 | |||
| 213 | bgc->reg_dat = devm_ioremap(dev, res_dat->start, dat_sz); | ||
| 214 | if (!bgc->reg_dat) | ||
| 215 | return -ENOMEM; | ||
| 216 | |||
| 217 | res_set = platform_get_resource_byname(pdev, IORESOURCE_MEM, "set"); | ||
| 218 | res_clr = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clr"); | ||
| 219 | if (res_set && res_clr) { | ||
| 220 | if (resource_size(res_set) != resource_size(res_clr) || | ||
| 221 | resource_size(res_set) != dat_sz) | ||
| 222 | return -EINVAL; | ||
| 223 | |||
| 224 | bgc->reg_set = devm_ioremap(dev, res_set->start, dat_sz); | ||
| 225 | bgc->reg_clr = devm_ioremap(dev, res_clr->start, dat_sz); | ||
| 226 | if (!bgc->reg_set || !bgc->reg_clr) | ||
| 227 | return -ENOMEM; | ||
| 228 | } else if (res_set || res_clr) { | ||
| 229 | return -EINVAL; | ||
| 230 | } | ||
| 231 | |||
| 232 | spin_lock_init(&bgc->lock); | ||
| 233 | |||
| 234 | bgc->bits = bits; | ||
| 235 | bgc->big_endian_bits = !strcmp(platid->name, "basic-mmio-gpio-be"); | ||
| 236 | bgc->data = bgpio_in(bgc); | ||
| 237 | |||
| 238 | bgc->gc.ngpio = bits; | ||
| 239 | bgc->gc.direction_input = bgpio_dir_in; | ||
| 240 | bgc->gc.direction_output = bgpio_dir_out; | ||
| 241 | bgc->gc.get = bgpio_get; | ||
| 242 | bgc->gc.set = bgpio_set; | ||
| 243 | bgc->gc.dev = dev; | ||
| 244 | bgc->gc.label = dev_name(dev); | ||
| 245 | |||
| 246 | if (pdata) | ||
| 247 | bgc->gc.base = pdata->base; | ||
| 248 | else | ||
| 249 | bgc->gc.base = -1; | ||
| 250 | |||
| 251 | dev_set_drvdata(dev, bgc); | ||
| 252 | |||
| 253 | ret = gpiochip_add(&bgc->gc); | ||
| 254 | if (ret) | ||
| 255 | dev_err(dev, "gpiochip_add() failed: %d\n", ret); | ||
| 256 | |||
| 257 | return ret; | ||
| 258 | } | ||
| 259 | |||
| 260 | static int __devexit bgpio_remove(struct platform_device *pdev) | ||
| 261 | { | ||
| 262 | struct bgpio_chip *bgc = dev_get_drvdata(&pdev->dev); | ||
| 263 | |||
| 264 | return gpiochip_remove(&bgc->gc); | ||
| 265 | } | ||
| 266 | |||
| 267 | static const struct platform_device_id bgpio_id_table[] = { | ||
| 268 | { "basic-mmio-gpio", }, | ||
| 269 | { "basic-mmio-gpio-be", }, | ||
| 270 | {}, | ||
| 271 | }; | ||
| 272 | MODULE_DEVICE_TABLE(platform, bgpio_id_table); | ||
| 273 | |||
| 274 | static struct platform_driver bgpio_driver = { | ||
| 275 | .driver = { | ||
| 276 | .name = "basic-mmio-gpio", | ||
| 277 | }, | ||
| 278 | .id_table = bgpio_id_table, | ||
| 279 | .probe = bgpio_probe, | ||
| 280 | .remove = __devexit_p(bgpio_remove), | ||
| 281 | }; | ||
| 282 | |||
| 283 | static int __init bgpio_init(void) | ||
| 284 | { | ||
| 285 | return platform_driver_register(&bgpio_driver); | ||
| 286 | } | ||
| 287 | module_init(bgpio_init); | ||
| 288 | |||
| 289 | static void __exit bgpio_exit(void) | ||
| 290 | { | ||
| 291 | platform_driver_unregister(&bgpio_driver); | ||
| 292 | } | ||
| 293 | module_exit(bgpio_exit); | ||
| 294 | |||
| 295 | MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers"); | ||
| 296 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); | ||
| 297 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 8383a8d7f994..64db9dc3a275 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c | |||
| @@ -18,10 +18,12 @@ | |||
| 18 | /* Supports: | 18 | /* Supports: |
| 19 | * Moorestown platform Langwell chip. | 19 | * Moorestown platform Langwell chip. |
| 20 | * Medfield platform Penwell chip. | 20 | * Medfield platform Penwell chip. |
| 21 | * Whitney point. | ||
| 21 | */ | 22 | */ |
| 22 | 23 | ||
| 23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 24 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
| 26 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 26 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
| 27 | #include <linux/stddef.h> | 29 | #include <linux/stddef.h> |
| @@ -158,15 +160,15 @@ static int lnw_irq_type(unsigned irq, unsigned type) | |||
| 158 | spin_unlock_irqrestore(&lnw->lock, flags); | 160 | spin_unlock_irqrestore(&lnw->lock, flags); |
| 159 | 161 | ||
| 160 | return 0; | 162 | return 0; |
| 161 | }; | 163 | } |
| 162 | 164 | ||
| 163 | static void lnw_irq_unmask(unsigned irq) | 165 | static void lnw_irq_unmask(unsigned irq) |
| 164 | { | 166 | { |
| 165 | }; | 167 | } |
| 166 | 168 | ||
| 167 | static void lnw_irq_mask(unsigned irq) | 169 | static void lnw_irq_mask(unsigned irq) |
| 168 | { | 170 | { |
| 169 | }; | 171 | } |
| 170 | 172 | ||
| 171 | static struct irq_chip lnw_irqchip = { | 173 | static struct irq_chip lnw_irqchip = { |
| 172 | .name = "LNW-GPIO", | 174 | .name = "LNW-GPIO", |
| @@ -300,9 +302,88 @@ static struct pci_driver lnw_gpio_driver = { | |||
| 300 | .probe = lnw_gpio_probe, | 302 | .probe = lnw_gpio_probe, |
| 301 | }; | 303 | }; |
| 302 | 304 | ||
| 305 | |||
| 306 | static int __devinit wp_gpio_probe(struct platform_device *pdev) | ||
| 307 | { | ||
| 308 | struct lnw_gpio *lnw; | ||
| 309 | struct gpio_chip *gc; | ||
| 310 | struct resource *rc; | ||
| 311 | int retval = 0; | ||
| 312 | |||
| 313 | rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 314 | if (!rc) | ||
| 315 | return -EINVAL; | ||
| 316 | |||
| 317 | lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); | ||
| 318 | if (!lnw) { | ||
| 319 | dev_err(&pdev->dev, | ||
| 320 | "can't allocate whitneypoint_gpio chip data\n"); | ||
| 321 | return -ENOMEM; | ||
| 322 | } | ||
| 323 | lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc)); | ||
| 324 | if (lnw->reg_base == NULL) { | ||
| 325 | retval = -EINVAL; | ||
| 326 | goto err_kmalloc; | ||
| 327 | } | ||
| 328 | spin_lock_init(&lnw->lock); | ||
| 329 | gc = &lnw->chip; | ||
| 330 | gc->label = dev_name(&pdev->dev); | ||
| 331 | gc->owner = THIS_MODULE; | ||
| 332 | gc->direction_input = lnw_gpio_direction_input; | ||
| 333 | gc->direction_output = lnw_gpio_direction_output; | ||
| 334 | gc->get = lnw_gpio_get; | ||
| 335 | gc->set = lnw_gpio_set; | ||
| 336 | gc->to_irq = NULL; | ||
| 337 | gc->base = 0; | ||
| 338 | gc->ngpio = 64; | ||
| 339 | gc->can_sleep = 0; | ||
| 340 | retval = gpiochip_add(gc); | ||
| 341 | if (retval) { | ||
| 342 | dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n", | ||
| 343 | retval); | ||
| 344 | goto err_ioremap; | ||
| 345 | } | ||
| 346 | platform_set_drvdata(pdev, lnw); | ||
| 347 | return 0; | ||
| 348 | err_ioremap: | ||
| 349 | iounmap(lnw->reg_base); | ||
| 350 | err_kmalloc: | ||
| 351 | kfree(lnw); | ||
| 352 | return retval; | ||
| 353 | } | ||
| 354 | |||
| 355 | static int __devexit wp_gpio_remove(struct platform_device *pdev) | ||
| 356 | { | ||
| 357 | struct lnw_gpio *lnw = platform_get_drvdata(pdev); | ||
| 358 | int err; | ||
| 359 | err = gpiochip_remove(&lnw->chip); | ||
| 360 | if (err) | ||
| 361 | dev_err(&pdev->dev, "failed to remove gpio_chip.\n"); | ||
| 362 | iounmap(lnw->reg_base); | ||
| 363 | kfree(lnw); | ||
| 364 | platform_set_drvdata(pdev, NULL); | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | static struct platform_driver wp_gpio_driver = { | ||
| 369 | .probe = wp_gpio_probe, | ||
| 370 | .remove = __devexit_p(wp_gpio_remove), | ||
| 371 | .driver = { | ||
| 372 | .name = "wp_gpio", | ||
| 373 | .owner = THIS_MODULE, | ||
| 374 | }, | ||
| 375 | }; | ||
| 376 | |||
| 303 | static int __init lnw_gpio_init(void) | 377 | static int __init lnw_gpio_init(void) |
| 304 | { | 378 | { |
| 305 | return pci_register_driver(&lnw_gpio_driver); | 379 | int ret; |
| 380 | ret = pci_register_driver(&lnw_gpio_driver); | ||
| 381 | if (ret < 0) | ||
| 382 | return ret; | ||
| 383 | ret = platform_driver_register(&wp_gpio_driver); | ||
| 384 | if (ret < 0) | ||
| 385 | pci_unregister_driver(&lnw_gpio_driver); | ||
| 386 | return ret; | ||
| 306 | } | 387 | } |
| 307 | 388 | ||
| 308 | device_initcall(lnw_gpio_init); | 389 | device_initcall(lnw_gpio_init); |
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c new file mode 100644 index 000000000000..0eba0a75c804 --- /dev/null +++ b/drivers/gpio/pch_gpio.c | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; version 2 of the License. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | ||
| 16 | */ | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/pci.h> | ||
| 19 | #include <linux/gpio.h> | ||
| 20 | |||
| 21 | #define PCH_GPIO_ALL_PINS 0xfff /* Mask for GPIO pins 0 to 11 */ | ||
| 22 | #define GPIO_NUM_PINS 12 /* Specifies number of GPIO PINS GPIO0-GPIO11 */ | ||
| 23 | |||
| 24 | struct pch_regs { | ||
| 25 | u32 ien; | ||
| 26 | u32 istatus; | ||
| 27 | u32 idisp; | ||
| 28 | u32 iclr; | ||
| 29 | u32 imask; | ||
| 30 | u32 imaskclr; | ||
| 31 | u32 po; | ||
| 32 | u32 pi; | ||
| 33 | u32 pm; | ||
| 34 | u32 im0; | ||
| 35 | u32 im1; | ||
| 36 | u32 reserved[4]; | ||
| 37 | u32 reset; | ||
| 38 | }; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * struct pch_gpio_reg_data - The register store data. | ||
| 42 | * @po_reg: To store contents of PO register. | ||
| 43 | * @pm_reg: To store contents of PM register. | ||
| 44 | */ | ||
| 45 | struct pch_gpio_reg_data { | ||
| 46 | u32 po_reg; | ||
| 47 | u32 pm_reg; | ||
| 48 | }; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * struct pch_gpio - GPIO private data structure. | ||
| 52 | * @base: PCI base address of Memory mapped I/O register. | ||
| 53 | * @reg: Memory mapped PCH GPIO register list. | ||
| 54 | * @dev: Pointer to device structure. | ||
| 55 | * @gpio: Data for GPIO infrastructure. | ||
| 56 | * @pch_gpio_reg: Memory mapped Register data is saved here | ||
| 57 | * when suspend. | ||
| 58 | */ | ||
| 59 | struct pch_gpio { | ||
| 60 | void __iomem *base; | ||
| 61 | struct pch_regs __iomem *reg; | ||
| 62 | struct device *dev; | ||
| 63 | struct gpio_chip gpio; | ||
| 64 | struct pch_gpio_reg_data pch_gpio_reg; | ||
| 65 | struct mutex lock; | ||
| 66 | }; | ||
| 67 | |||
| 68 | static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) | ||
| 69 | { | ||
| 70 | u32 reg_val; | ||
| 71 | struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); | ||
| 72 | |||
| 73 | mutex_lock(&chip->lock); | ||
| 74 | reg_val = ioread32(&chip->reg->po); | ||
| 75 | if (val) | ||
| 76 | reg_val |= (1 << nr); | ||
| 77 | else | ||
| 78 | reg_val &= ~(1 << nr); | ||
| 79 | |||
| 80 | iowrite32(reg_val, &chip->reg->po); | ||
| 81 | mutex_unlock(&chip->lock); | ||
| 82 | } | ||
| 83 | |||
| 84 | static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr) | ||
| 85 | { | ||
| 86 | struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); | ||
| 87 | |||
| 88 | return ioread32(&chip->reg->pi) & (1 << nr); | ||
| 89 | } | ||
| 90 | |||
| 91 | static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, | ||
| 92 | int val) | ||
| 93 | { | ||
| 94 | struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); | ||
| 95 | u32 pm; | ||
| 96 | u32 reg_val; | ||
| 97 | |||
| 98 | mutex_lock(&chip->lock); | ||
| 99 | pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; | ||
| 100 | pm |= (1 << nr); | ||
| 101 | iowrite32(pm, &chip->reg->pm); | ||
| 102 | |||
| 103 | reg_val = ioread32(&chip->reg->po); | ||
| 104 | if (val) | ||
| 105 | reg_val |= (1 << nr); | ||
| 106 | else | ||
| 107 | reg_val &= ~(1 << nr); | ||
| 108 | |||
| 109 | mutex_unlock(&chip->lock); | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | ||
| 115 | { | ||
| 116 | struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio); | ||
| 117 | u32 pm; | ||
| 118 | |||
| 119 | mutex_lock(&chip->lock); | ||
| 120 | pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/ | ||
| 121 | pm &= ~(1 << nr); | ||
| 122 | iowrite32(pm, &chip->reg->pm); | ||
| 123 | mutex_unlock(&chip->lock); | ||
| 124 | |||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Save register configuration and disable interrupts. | ||
| 130 | */ | ||
| 131 | static void pch_gpio_save_reg_conf(struct pch_gpio *chip) | ||
| 132 | { | ||
| 133 | chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po); | ||
| 134 | chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm); | ||
| 135 | } | ||
| 136 | |||
| 137 | /* | ||
| 138 | * This function restores the register configuration of the GPIO device. | ||
| 139 | */ | ||
| 140 | static void pch_gpio_restore_reg_conf(struct pch_gpio *chip) | ||
| 141 | { | ||
| 142 | /* to store contents of PO register */ | ||
| 143 | iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po); | ||
| 144 | /* to store contents of PM register */ | ||
| 145 | iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm); | ||
| 146 | } | ||
| 147 | |||
| 148 | static void pch_gpio_setup(struct pch_gpio *chip) | ||
| 149 | { | ||
| 150 | struct gpio_chip *gpio = &chip->gpio; | ||
| 151 | |||
| 152 | gpio->label = dev_name(chip->dev); | ||
| 153 | gpio->owner = THIS_MODULE; | ||
| 154 | gpio->direction_input = pch_gpio_direction_input; | ||
| 155 | gpio->get = pch_gpio_get; | ||
| 156 | gpio->direction_output = pch_gpio_direction_output; | ||
| 157 | gpio->set = pch_gpio_set; | ||
| 158 | gpio->dbg_show = NULL; | ||
| 159 | gpio->base = -1; | ||
| 160 | gpio->ngpio = GPIO_NUM_PINS; | ||
| 161 | gpio->can_sleep = 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int __devinit pch_gpio_probe(struct pci_dev *pdev, | ||
| 165 | const struct pci_device_id *id) | ||
| 166 | { | ||
| 167 | s32 ret; | ||
| 168 | struct pch_gpio *chip; | ||
| 169 | |||
| 170 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
| 171 | if (chip == NULL) | ||
| 172 | return -ENOMEM; | ||
| 173 | |||
| 174 | chip->dev = &pdev->dev; | ||
| 175 | ret = pci_enable_device(pdev); | ||
| 176 | if (ret) { | ||
| 177 | dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__); | ||
| 178 | goto err_pci_enable; | ||
| 179 | } | ||
| 180 | |||
| 181 | ret = pci_request_regions(pdev, KBUILD_MODNAME); | ||
| 182 | if (ret) { | ||
| 183 | dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret); | ||
| 184 | goto err_request_regions; | ||
| 185 | } | ||
| 186 | |||
| 187 | chip->base = pci_iomap(pdev, 1, 0); | ||
| 188 | if (chip->base == 0) { | ||
| 189 | dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__); | ||
| 190 | ret = -ENOMEM; | ||
| 191 | goto err_iomap; | ||
| 192 | } | ||
| 193 | |||
| 194 | chip->reg = chip->base; | ||
| 195 | pci_set_drvdata(pdev, chip); | ||
| 196 | mutex_init(&chip->lock); | ||
| 197 | pch_gpio_setup(chip); | ||
| 198 | ret = gpiochip_add(&chip->gpio); | ||
| 199 | if (ret) { | ||
| 200 | dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n"); | ||
| 201 | goto err_gpiochip_add; | ||
| 202 | } | ||
| 203 | |||
| 204 | return 0; | ||
| 205 | |||
| 206 | err_gpiochip_add: | ||
| 207 | pci_iounmap(pdev, chip->base); | ||
| 208 | |||
| 209 | err_iomap: | ||
| 210 | pci_release_regions(pdev); | ||
| 211 | |||
| 212 | err_request_regions: | ||
| 213 | pci_disable_device(pdev); | ||
| 214 | |||
| 215 | err_pci_enable: | ||
| 216 | kfree(chip); | ||
| 217 | dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret); | ||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | |||
| 221 | static void __devexit pch_gpio_remove(struct pci_dev *pdev) | ||
| 222 | { | ||
| 223 | int err; | ||
| 224 | struct pch_gpio *chip = pci_get_drvdata(pdev); | ||
| 225 | |||
| 226 | err = gpiochip_remove(&chip->gpio); | ||
| 227 | if (err) | ||
| 228 | dev_err(&pdev->dev, "Failed gpiochip_remove\n"); | ||
| 229 | |||
| 230 | pci_iounmap(pdev, chip->base); | ||
| 231 | pci_release_regions(pdev); | ||
| 232 | pci_disable_device(pdev); | ||
| 233 | kfree(chip); | ||
| 234 | } | ||
| 235 | |||
| 236 | #ifdef CONFIG_PM | ||
| 237 | static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 238 | { | ||
| 239 | s32 ret; | ||
| 240 | struct pch_gpio *chip = pci_get_drvdata(pdev); | ||
| 241 | |||
| 242 | pch_gpio_save_reg_conf(chip); | ||
| 243 | pch_gpio_restore_reg_conf(chip); | ||
| 244 | |||
| 245 | ret = pci_save_state(pdev); | ||
| 246 | if (ret) { | ||
| 247 | dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret); | ||
| 248 | return ret; | ||
| 249 | } | ||
| 250 | pci_disable_device(pdev); | ||
| 251 | pci_set_power_state(pdev, PCI_D0); | ||
| 252 | ret = pci_enable_wake(pdev, PCI_D0, 1); | ||
| 253 | if (ret) | ||
| 254 | dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret); | ||
| 255 | |||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int pch_gpio_resume(struct pci_dev *pdev) | ||
| 260 | { | ||
| 261 | s32 ret; | ||
| 262 | struct pch_gpio *chip = pci_get_drvdata(pdev); | ||
| 263 | |||
| 264 | ret = pci_enable_wake(pdev, PCI_D0, 0); | ||
| 265 | |||
| 266 | pci_set_power_state(pdev, PCI_D0); | ||
| 267 | ret = pci_enable_device(pdev); | ||
| 268 | if (ret) { | ||
| 269 | dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret); | ||
| 270 | return ret; | ||
| 271 | } | ||
| 272 | pci_restore_state(pdev); | ||
| 273 | |||
| 274 | iowrite32(0x01, &chip->reg->reset); | ||
| 275 | iowrite32(0x00, &chip->reg->reset); | ||
| 276 | pch_gpio_restore_reg_conf(chip); | ||
| 277 | |||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | #else | ||
| 281 | #define pch_gpio_suspend NULL | ||
| 282 | #define pch_gpio_resume NULL | ||
| 283 | #endif | ||
| 284 | |||
| 285 | static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { | ||
| 286 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, | ||
| 287 | { 0, } | ||
| 288 | }; | ||
| 289 | |||
| 290 | static struct pci_driver pch_gpio_driver = { | ||
| 291 | .name = "pch_gpio", | ||
| 292 | .id_table = pch_gpio_pcidev_id, | ||
| 293 | .probe = pch_gpio_probe, | ||
| 294 | .remove = __devexit_p(pch_gpio_remove), | ||
| 295 | .suspend = pch_gpio_suspend, | ||
| 296 | .resume = pch_gpio_resume | ||
| 297 | }; | ||
| 298 | |||
| 299 | static int __init pch_gpio_pci_init(void) | ||
| 300 | { | ||
| 301 | return pci_register_driver(&pch_gpio_driver); | ||
| 302 | } | ||
| 303 | module_init(pch_gpio_pci_init); | ||
| 304 | |||
| 305 | static void __exit pch_gpio_pci_exit(void) | ||
| 306 | { | ||
| 307 | pci_unregister_driver(&pch_gpio_driver); | ||
| 308 | } | ||
| 309 | module_exit(pch_gpio_pci_exit); | ||
| 310 | |||
| 311 | MODULE_DESCRIPTION("PCH GPIO PCI Driver"); | ||
| 312 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index ddd053108a13..45293662e950 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/timbgpio.c | |||
| @@ -47,6 +47,7 @@ struct timbgpio { | |||
| 47 | spinlock_t lock; /* mutual exclusion */ | 47 | spinlock_t lock; /* mutual exclusion */ |
| 48 | struct gpio_chip gpio; | 48 | struct gpio_chip gpio; |
| 49 | int irq_base; | 49 | int irq_base; |
| 50 | unsigned long last_ier; | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, | 53 | static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, |
| @@ -112,16 +113,24 @@ static void timbgpio_irq_disable(unsigned irq) | |||
| 112 | { | 113 | { |
| 113 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 114 | struct timbgpio *tgpio = get_irq_chip_data(irq); |
| 114 | int offset = irq - tgpio->irq_base; | 115 | int offset = irq - tgpio->irq_base; |
| 116 | unsigned long flags; | ||
| 115 | 117 | ||
| 116 | timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 0); | 118 | spin_lock_irqsave(&tgpio->lock, flags); |
| 119 | tgpio->last_ier &= ~(1 << offset); | ||
| 120 | iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); | ||
| 121 | spin_unlock_irqrestore(&tgpio->lock, flags); | ||
| 117 | } | 122 | } |
| 118 | 123 | ||
| 119 | static void timbgpio_irq_enable(unsigned irq) | 124 | static void timbgpio_irq_enable(unsigned irq) |
| 120 | { | 125 | { |
| 121 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 126 | struct timbgpio *tgpio = get_irq_chip_data(irq); |
| 122 | int offset = irq - tgpio->irq_base; | 127 | int offset = irq - tgpio->irq_base; |
| 128 | unsigned long flags; | ||
| 123 | 129 | ||
| 124 | timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 1); | 130 | spin_lock_irqsave(&tgpio->lock, flags); |
| 131 | tgpio->last_ier |= 1 << offset; | ||
| 132 | iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); | ||
| 133 | spin_unlock_irqrestore(&tgpio->lock, flags); | ||
| 125 | } | 134 | } |
| 126 | 135 | ||
| 127 | static int timbgpio_irq_type(unsigned irq, unsigned trigger) | 136 | static int timbgpio_irq_type(unsigned irq, unsigned trigger) |
| @@ -194,8 +203,16 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) | |||
| 194 | ipr = ioread32(tgpio->membase + TGPIO_IPR); | 203 | ipr = ioread32(tgpio->membase + TGPIO_IPR); |
| 195 | iowrite32(ipr, tgpio->membase + TGPIO_ICR); | 204 | iowrite32(ipr, tgpio->membase + TGPIO_ICR); |
| 196 | 205 | ||
| 206 | /* | ||
| 207 | * Some versions of the hardware trash the IER register if more than | ||
| 208 | * one interrupt is received simultaneously. | ||
| 209 | */ | ||
| 210 | iowrite32(0, tgpio->membase + TGPIO_IER); | ||
| 211 | |||
| 197 | for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) | 212 | for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) |
| 198 | generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); | 213 | generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); |
| 214 | |||
| 215 | iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); | ||
| 199 | } | 216 | } |
| 200 | 217 | ||
| 201 | static struct irq_chip timbgpio_irqchip = { | 218 | static struct irq_chip timbgpio_irqchip = { |
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c index 0acf6396e068..202581808bdc 100644 --- a/drivers/media/IR/lirc_dev.c +++ b/drivers/media/IR/lirc_dev.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
| 28 | #include <linux/poll.h> | 28 | #include <linux/poll.h> |
| 29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
| 30 | #include <linux/errno.h> | ||
| 31 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
| 32 | #include <linux/wait.h> | 31 | #include <linux/wait.h> |
| 33 | #include <linux/unistd.h> | 32 | #include <linux/unistd.h> |
diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c index f540ff96c53f..e61db9dfebef 100644 --- a/drivers/platform/x86/intel_pmic_gpio.c +++ b/drivers/platform/x86/intel_pmic_gpio.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
| 30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
| 31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
| 32 | #include <linux/interrupt.h> | ||
| 33 | #include <asm/intel_scu_ipc.h> | 32 | #include <asm/intel_scu_ipc.h> |
| 34 | #include <linux/device.h> | 33 | #include <linux/device.h> |
| 35 | #include <linux/intel_pmic_gpio.h> | 34 | #include <linux/intel_pmic_gpio.h> |
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index 3222fa3c808c..0f4a53bdaa3c 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c | |||
| @@ -192,7 +192,7 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv) | |||
| 192 | out:return 0; | 192 | out:return 0; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | static struct device rio_bus = { | 195 | struct device rio_bus = { |
| 196 | .init_name = "rapidio", | 196 | .init_name = "rapidio", |
| 197 | }; | 197 | }; |
| 198 | 198 | ||
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 8070e074c739..1eb82c4c712e 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
| @@ -48,7 +48,7 @@ DEFINE_SPINLOCK(rio_global_list_lock); | |||
| 48 | static int next_destid = 0; | 48 | static int next_destid = 0; |
| 49 | static int next_switchid = 0; | 49 | static int next_switchid = 0; |
| 50 | static int next_net = 0; | 50 | static int next_net = 0; |
| 51 | static int next_comptag; | 51 | static int next_comptag = 1; |
| 52 | 52 | ||
| 53 | static struct timer_list rio_enum_timer = | 53 | static struct timer_list rio_enum_timer = |
| 54 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); | 54 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); |
| @@ -121,27 +121,6 @@ static int rio_clear_locks(struct rio_mport *port) | |||
| 121 | u32 result; | 121 | u32 result; |
| 122 | int ret = 0; | 122 | int ret = 0; |
| 123 | 123 | ||
| 124 | /* Assign component tag to all devices */ | ||
| 125 | next_comptag = 1; | ||
| 126 | rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++); | ||
| 127 | |||
| 128 | list_for_each_entry(rdev, &rio_devices, global_list) { | ||
| 129 | /* Mark device as discovered */ | ||
| 130 | rio_read_config_32(rdev, | ||
| 131 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 132 | &result); | ||
| 133 | rio_write_config_32(rdev, | ||
| 134 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 135 | result | RIO_PORT_GEN_DISCOVERED); | ||
| 136 | |||
| 137 | rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag); | ||
| 138 | rdev->comp_tag = next_comptag++; | ||
| 139 | if (next_comptag >= 0x10000) { | ||
| 140 | pr_err("RIO: Component Tag Counter Overflow\n"); | ||
| 141 | break; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | /* Release host device id locks */ | 124 | /* Release host device id locks */ |
| 146 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, | 125 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, |
| 147 | port->host_deviceid); | 126 | port->host_deviceid); |
| @@ -162,6 +141,15 @@ static int rio_clear_locks(struct rio_mport *port) | |||
| 162 | rdev->vid, rdev->did); | 141 | rdev->vid, rdev->did); |
| 163 | ret = -EINVAL; | 142 | ret = -EINVAL; |
| 164 | } | 143 | } |
| 144 | |||
| 145 | /* Mark device as discovered and enable master */ | ||
| 146 | rio_read_config_32(rdev, | ||
| 147 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 148 | &result); | ||
| 149 | result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER; | ||
| 150 | rio_write_config_32(rdev, | ||
| 151 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
| 152 | result); | ||
| 165 | } | 153 | } |
| 166 | 154 | ||
| 167 | return ret; | 155 | return ret; |
| @@ -420,11 +408,27 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
| 420 | hopcount, RIO_EFB_ERR_MGMNT); | 408 | hopcount, RIO_EFB_ERR_MGMNT); |
| 421 | } | 409 | } |
| 422 | 410 | ||
| 411 | if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { | ||
| 412 | rio_mport_read_config_32(port, destid, hopcount, | ||
| 413 | RIO_SWP_INFO_CAR, &rdev->swpinfo); | ||
| 414 | } | ||
| 415 | |||
| 423 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, | 416 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, |
| 424 | &rdev->src_ops); | 417 | &rdev->src_ops); |
| 425 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, | 418 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, |
| 426 | &rdev->dst_ops); | 419 | &rdev->dst_ops); |
| 427 | 420 | ||
| 421 | if (do_enum) { | ||
| 422 | /* Assign component tag to device */ | ||
| 423 | if (next_comptag >= 0x10000) { | ||
| 424 | pr_err("RIO: Component Tag Counter Overflow\n"); | ||
| 425 | goto cleanup; | ||
| 426 | } | ||
| 427 | rio_mport_write_config_32(port, destid, hopcount, | ||
| 428 | RIO_COMPONENT_TAG_CSR, next_comptag); | ||
| 429 | rdev->comp_tag = next_comptag++; | ||
| 430 | } | ||
| 431 | |||
| 428 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { | 432 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { |
| 429 | if (do_enum) { | 433 | if (do_enum) { |
| 430 | rio_set_device_id(port, destid, hopcount, next_destid); | 434 | rio_set_device_id(port, destid, hopcount, next_destid); |
| @@ -439,9 +443,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
| 439 | 443 | ||
| 440 | /* If a PE has both switch and other functions, show it as a switch */ | 444 | /* If a PE has both switch and other functions, show it as a switch */ |
| 441 | if (rio_is_switch(rdev)) { | 445 | if (rio_is_switch(rdev)) { |
| 442 | rio_mport_read_config_32(port, destid, hopcount, | 446 | rswitch = kzalloc(sizeof(*rswitch) + |
| 443 | RIO_SWP_INFO_CAR, &rdev->swpinfo); | 447 | RIO_GET_TOTAL_PORTS(rdev->swpinfo) * |
| 444 | rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); | 448 | sizeof(rswitch->nextdev[0]), |
| 449 | GFP_KERNEL); | ||
| 445 | if (!rswitch) | 450 | if (!rswitch) |
| 446 | goto cleanup; | 451 | goto cleanup; |
| 447 | rswitch->switchid = next_switchid; | 452 | rswitch->switchid = next_switchid; |
| @@ -458,6 +463,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
| 458 | rdid++) | 463 | rdid++) |
| 459 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; | 464 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; |
| 460 | rdev->rswitch = rswitch; | 465 | rdev->rswitch = rswitch; |
| 466 | rswitch->rdev = rdev; | ||
| 461 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, | 467 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, |
| 462 | rdev->rswitch->switchid); | 468 | rdev->rswitch->switchid); |
| 463 | rio_switch_init(rdev, do_enum); | 469 | rio_switch_init(rdev, do_enum); |
| @@ -478,6 +484,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
| 478 | } | 484 | } |
| 479 | 485 | ||
| 480 | rdev->dev.bus = &rio_bus_type; | 486 | rdev->dev.bus = &rio_bus_type; |
| 487 | rdev->dev.parent = &rio_bus; | ||
| 481 | 488 | ||
| 482 | device_initialize(&rdev->dev); | 489 | device_initialize(&rdev->dev); |
| 483 | rdev->dev.release = rio_release_dev; | 490 | rdev->dev.release = rio_release_dev; |
| @@ -718,86 +725,53 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) | |||
| 718 | } | 725 | } |
| 719 | 726 | ||
| 720 | /** | 727 | /** |
| 721 | * rio_get_swpinfo_inport- Gets the ingress port number | ||
| 722 | * @mport: Master port to send transaction | ||
| 723 | * @destid: Destination ID associated with the switch | ||
| 724 | * @hopcount: Number of hops to the device | ||
| 725 | * | ||
| 726 | * Returns port number being used to access the switch device. | ||
| 727 | */ | ||
| 728 | static u8 | ||
| 729 | rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount) | ||
| 730 | { | ||
| 731 | u32 result; | ||
| 732 | |||
| 733 | rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, | ||
| 734 | &result); | ||
| 735 | |||
| 736 | return (u8) (result & 0xff); | ||
| 737 | } | ||
| 738 | |||
| 739 | /** | ||
| 740 | * rio_get_swpinfo_tports- Gets total number of ports on the switch | ||
| 741 | * @mport: Master port to send transaction | ||
| 742 | * @destid: Destination ID associated with the switch | ||
| 743 | * @hopcount: Number of hops to the device | ||
| 744 | * | ||
| 745 | * Returns total numbers of ports implemented by the switch device. | ||
| 746 | */ | ||
| 747 | static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid, | ||
| 748 | u8 hopcount) | ||
| 749 | { | ||
| 750 | u32 result; | ||
| 751 | |||
| 752 | rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR, | ||
| 753 | &result); | ||
| 754 | |||
| 755 | return RIO_GET_TOTAL_PORTS(result); | ||
| 756 | } | ||
| 757 | |||
| 758 | /** | ||
| 759 | * rio_net_add_mport- Add a master port to a RIO network | ||
| 760 | * @net: RIO network | ||
| 761 | * @port: Master port to add | ||
| 762 | * | ||
| 763 | * Adds a master port to the network list of associated master | ||
| 764 | * ports.. | ||
| 765 | */ | ||
| 766 | static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port) | ||
| 767 | { | ||
| 768 | spin_lock(&rio_global_list_lock); | ||
| 769 | list_add_tail(&port->nnode, &net->mports); | ||
| 770 | spin_unlock(&rio_global_list_lock); | ||
| 771 | } | ||
| 772 | |||
| 773 | /** | ||
| 774 | * rio_enum_peer- Recursively enumerate a RIO network through a master port | 728 | * rio_enum_peer- Recursively enumerate a RIO network through a master port |
| 775 | * @net: RIO network being enumerated | 729 | * @net: RIO network being enumerated |
| 776 | * @port: Master port to send transactions | 730 | * @port: Master port to send transactions |
| 777 | * @hopcount: Number of hops into the network | 731 | * @hopcount: Number of hops into the network |
| 732 | * @prev: Previous RIO device connected to the enumerated one | ||
| 733 | * @prev_port: Port on previous RIO device | ||
| 778 | * | 734 | * |
| 779 | * Recursively enumerates a RIO network. Transactions are sent via the | 735 | * Recursively enumerates a RIO network. Transactions are sent via the |
| 780 | * master port passed in @port. | 736 | * master port passed in @port. |
| 781 | */ | 737 | */ |
| 782 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | 738 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, |
| 783 | u8 hopcount) | 739 | u8 hopcount, struct rio_dev *prev, int prev_port) |
| 784 | { | 740 | { |
| 785 | int port_num; | 741 | int port_num; |
| 786 | int num_ports; | ||
| 787 | int cur_destid; | 742 | int cur_destid; |
| 788 | int sw_destid; | 743 | int sw_destid; |
| 789 | int sw_inport; | 744 | int sw_inport; |
| 790 | struct rio_dev *rdev; | 745 | struct rio_dev *rdev; |
| 791 | u16 destid; | 746 | u16 destid; |
| 747 | u32 regval; | ||
| 792 | int tmp; | 748 | int tmp; |
| 793 | 749 | ||
| 750 | if (rio_mport_chk_dev_access(port, | ||
| 751 | RIO_ANY_DESTID(port->sys_size), hopcount)) { | ||
| 752 | pr_debug("RIO: device access check failed\n"); | ||
| 753 | return -1; | ||
| 754 | } | ||
| 755 | |||
| 794 | if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { | 756 | if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { |
| 795 | pr_debug("RIO: PE already discovered by this host\n"); | 757 | pr_debug("RIO: PE already discovered by this host\n"); |
| 796 | /* | 758 | /* |
| 797 | * Already discovered by this host. Add it as another | 759 | * Already discovered by this host. Add it as another |
| 798 | * master port for the current network. | 760 | * link to the existing device. |
| 799 | */ | 761 | */ |
| 800 | rio_net_add_mport(net, port); | 762 | rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), |
| 763 | hopcount, RIO_COMPONENT_TAG_CSR, ®val); | ||
| 764 | |||
| 765 | if (regval) { | ||
| 766 | rdev = rio_get_comptag((regval & 0xffff), NULL); | ||
| 767 | |||
| 768 | if (rdev && prev && rio_is_switch(prev)) { | ||
| 769 | pr_debug("RIO: redundant path to %s\n", | ||
| 770 | rio_name(rdev)); | ||
| 771 | prev->rswitch->nextdev[prev_port] = rdev; | ||
| 772 | } | ||
| 773 | } | ||
| 774 | |||
| 801 | return 0; | 775 | return 0; |
| 802 | } | 776 | } |
| 803 | 777 | ||
| @@ -828,13 +802,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
| 828 | if (rdev) { | 802 | if (rdev) { |
| 829 | /* Add device to the global and bus/net specific list. */ | 803 | /* Add device to the global and bus/net specific list. */ |
| 830 | list_add_tail(&rdev->net_list, &net->devices); | 804 | list_add_tail(&rdev->net_list, &net->devices); |
| 805 | rdev->prev = prev; | ||
| 806 | if (prev && rio_is_switch(prev)) | ||
| 807 | prev->rswitch->nextdev[prev_port] = rdev; | ||
| 831 | } else | 808 | } else |
| 832 | return -1; | 809 | return -1; |
| 833 | 810 | ||
| 834 | if (rio_is_switch(rdev)) { | 811 | if (rio_is_switch(rdev)) { |
| 835 | next_switchid++; | 812 | next_switchid++; |
| 836 | sw_inport = rio_get_swpinfo_inport(port, | 813 | sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); |
| 837 | RIO_ANY_DESTID(port->sys_size), hopcount); | ||
| 838 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, | 814 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, |
| 839 | port->host_deviceid, sw_inport, 0); | 815 | port->host_deviceid, sw_inport, 0); |
| 840 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; | 816 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; |
| @@ -847,14 +823,14 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
| 847 | rdev->rswitch->route_table[destid] = sw_inport; | 823 | rdev->rswitch->route_table[destid] = sw_inport; |
| 848 | } | 824 | } |
| 849 | 825 | ||
| 850 | num_ports = | ||
| 851 | rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size), | ||
| 852 | hopcount); | ||
| 853 | pr_debug( | 826 | pr_debug( |
| 854 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 827 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
| 855 | rio_name(rdev), rdev->vid, rdev->did, num_ports); | 828 | rio_name(rdev), rdev->vid, rdev->did, |
| 829 | RIO_GET_TOTAL_PORTS(rdev->swpinfo)); | ||
| 856 | sw_destid = next_destid; | 830 | sw_destid = next_destid; |
| 857 | for (port_num = 0; port_num < num_ports; port_num++) { | 831 | for (port_num = 0; |
| 832 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); | ||
| 833 | port_num++) { | ||
| 858 | /*Enable Input Output Port (transmitter reviever)*/ | 834 | /*Enable Input Output Port (transmitter reviever)*/ |
| 859 | rio_enable_rx_tx_port(port, 0, | 835 | rio_enable_rx_tx_port(port, 0, |
| 860 | RIO_ANY_DESTID(port->sys_size), | 836 | RIO_ANY_DESTID(port->sys_size), |
| @@ -879,7 +855,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
| 879 | RIO_ANY_DESTID(port->sys_size), | 855 | RIO_ANY_DESTID(port->sys_size), |
| 880 | port_num, 0); | 856 | port_num, 0); |
| 881 | 857 | ||
| 882 | if (rio_enum_peer(net, port, hopcount + 1) < 0) | 858 | if (rio_enum_peer(net, port, hopcount + 1, |
| 859 | rdev, port_num) < 0) | ||
| 883 | return -1; | 860 | return -1; |
| 884 | 861 | ||
| 885 | /* Update routing tables */ | 862 | /* Update routing tables */ |
| @@ -945,10 +922,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
| 945 | */ | 922 | */ |
| 946 | static int rio_enum_complete(struct rio_mport *port) | 923 | static int rio_enum_complete(struct rio_mport *port) |
| 947 | { | 924 | { |
| 948 | u32 tag_csr; | 925 | u32 regval; |
| 949 | 926 | ||
| 950 | rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); | 927 | rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR, |
| 951 | return (tag_csr & 0xffff) ? 1 : 0; | 928 | ®val); |
| 929 | return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0; | ||
| 952 | } | 930 | } |
| 953 | 931 | ||
| 954 | /** | 932 | /** |
| @@ -966,7 +944,6 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
| 966 | u8 hopcount) | 944 | u8 hopcount) |
| 967 | { | 945 | { |
| 968 | u8 port_num, route_port; | 946 | u8 port_num, route_port; |
| 969 | int num_ports; | ||
| 970 | struct rio_dev *rdev; | 947 | struct rio_dev *rdev; |
| 971 | u16 ndestid; | 948 | u16 ndestid; |
| 972 | 949 | ||
| @@ -983,13 +960,14 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
| 983 | /* Associated destid is how we accessed this switch */ | 960 | /* Associated destid is how we accessed this switch */ |
| 984 | rdev->rswitch->destid = destid; | 961 | rdev->rswitch->destid = destid; |
| 985 | 962 | ||
| 986 | num_ports = rio_get_swpinfo_tports(port, destid, hopcount); | ||
| 987 | pr_debug( | 963 | pr_debug( |
| 988 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 964 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
| 989 | rio_name(rdev), rdev->vid, rdev->did, num_ports); | 965 | rio_name(rdev), rdev->vid, rdev->did, |
| 990 | for (port_num = 0; port_num < num_ports; port_num++) { | 966 | RIO_GET_TOTAL_PORTS(rdev->swpinfo)); |
| 991 | if (rio_get_swpinfo_inport(port, destid, hopcount) == | 967 | for (port_num = 0; |
| 992 | port_num) | 968 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); |
| 969 | port_num++) { | ||
| 970 | if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num) | ||
| 993 | continue; | 971 | continue; |
| 994 | 972 | ||
| 995 | if (rio_sport_is_active | 973 | if (rio_sport_is_active |
| @@ -1011,6 +989,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
| 1011 | break; | 989 | break; |
| 1012 | } | 990 | } |
| 1013 | 991 | ||
| 992 | if (ndestid == RIO_ANY_DESTID(port->sys_size)) | ||
| 993 | continue; | ||
| 1014 | rio_unlock_device(port, destid, hopcount); | 994 | rio_unlock_device(port, destid, hopcount); |
| 1015 | if (rio_disc_peer | 995 | if (rio_disc_peer |
| 1016 | (net, port, ndestid, hopcount + 1) < 0) | 996 | (net, port, ndestid, hopcount + 1) < 0) |
| @@ -1108,8 +1088,7 @@ static void rio_update_route_tables(struct rio_mport *port) | |||
| 1108 | if (rswitch->destid == destid) | 1088 | if (rswitch->destid == destid) |
| 1109 | continue; | 1089 | continue; |
| 1110 | 1090 | ||
| 1111 | sport = rio_get_swpinfo_inport(port, | 1091 | sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo); |
| 1112 | rswitch->destid, rswitch->hopcount); | ||
| 1113 | 1092 | ||
| 1114 | if (rswitch->add_entry) { | 1093 | if (rswitch->add_entry) { |
| 1115 | rio_route_add_entry(port, rswitch, | 1094 | rio_route_add_entry(port, rswitch, |
| @@ -1184,7 +1163,11 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
| 1184 | /* Enable Input Output Port (transmitter reviever) */ | 1163 | /* Enable Input Output Port (transmitter reviever) */ |
| 1185 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); | 1164 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); |
| 1186 | 1165 | ||
| 1187 | if (rio_enum_peer(net, mport, 0) < 0) { | 1166 | /* Set component tag for host */ |
| 1167 | rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, | ||
| 1168 | next_comptag++); | ||
| 1169 | |||
| 1170 | if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { | ||
| 1188 | /* A higher priority host won enumeration, bail. */ | 1171 | /* A higher priority host won enumeration, bail. */ |
| 1189 | printk(KERN_INFO | 1172 | printk(KERN_INFO |
| 1190 | "RIO: master port %d device has lost enumeration to a remote host\n", | 1173 | "RIO: master port %d device has lost enumeration to a remote host\n", |
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 00b475658356..137ed93ee33f 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c | |||
| @@ -40,9 +40,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch | |||
| 40 | char *str = buf; | 40 | char *str = buf; |
| 41 | int i; | 41 | int i; |
| 42 | 42 | ||
| 43 | if (!rdev->rswitch) | ||
| 44 | goto out; | ||
| 45 | |||
| 46 | for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); | 43 | for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); |
| 47 | i++) { | 44 | i++) { |
| 48 | if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE) | 45 | if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE) |
| @@ -52,7 +49,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch | |||
| 52 | rdev->rswitch->route_table[i]); | 49 | rdev->rswitch->route_table[i]); |
| 53 | } | 50 | } |
| 54 | 51 | ||
| 55 | out: | ||
| 56 | return (str - buf); | 52 | return (str - buf); |
| 57 | } | 53 | } |
| 58 | 54 | ||
| @@ -63,10 +59,11 @@ struct device_attribute rio_dev_attrs[] = { | |||
| 63 | __ATTR_RO(asm_did), | 59 | __ATTR_RO(asm_did), |
| 64 | __ATTR_RO(asm_vid), | 60 | __ATTR_RO(asm_vid), |
| 65 | __ATTR_RO(asm_rev), | 61 | __ATTR_RO(asm_rev), |
| 66 | __ATTR_RO(routes), | ||
| 67 | __ATTR_NULL, | 62 | __ATTR_NULL, |
| 68 | }; | 63 | }; |
| 69 | 64 | ||
| 65 | static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL); | ||
| 66 | |||
| 70 | static ssize_t | 67 | static ssize_t |
| 71 | rio_read_config(struct file *filp, struct kobject *kobj, | 68 | rio_read_config(struct file *filp, struct kobject *kobj, |
| 72 | struct bin_attribute *bin_attr, | 69 | struct bin_attribute *bin_attr, |
| @@ -218,7 +215,17 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) | |||
| 218 | { | 215 | { |
| 219 | int err = 0; | 216 | int err = 0; |
| 220 | 217 | ||
| 221 | err = sysfs_create_bin_file(&rdev->dev.kobj, &rio_config_attr); | 218 | err = device_create_bin_file(&rdev->dev, &rio_config_attr); |
| 219 | |||
| 220 | if (!err && rdev->rswitch) { | ||
| 221 | err = device_create_file(&rdev->dev, &dev_attr_routes); | ||
| 222 | if (!err && rdev->rswitch->sw_sysfs) | ||
| 223 | err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); | ||
| 224 | } | ||
| 225 | |||
| 226 | if (err) | ||
| 227 | pr_warning("RIO: Failed to create attribute file(s) for %s\n", | ||
| 228 | rio_name(rdev)); | ||
| 222 | 229 | ||
| 223 | return err; | 230 | return err; |
| 224 | } | 231 | } |
| @@ -231,5 +238,10 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) | |||
| 231 | */ | 238 | */ |
| 232 | void rio_remove_sysfs_dev_files(struct rio_dev *rdev) | 239 | void rio_remove_sysfs_dev_files(struct rio_dev *rdev) |
| 233 | { | 240 | { |
| 234 | sysfs_remove_bin_file(&rdev->dev.kobj, &rio_config_attr); | 241 | device_remove_bin_file(&rdev->dev, &rio_config_attr); |
| 242 | if (rdev->rswitch) { | ||
| 243 | device_remove_file(&rdev->dev, &dev_attr_routes); | ||
| 244 | if (rdev->rswitch->sw_sysfs) | ||
| 245 | rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); | ||
| 246 | } | ||
| 235 | } | 247 | } |
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 74e9d22d95fb..68cf0c99138a 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
| @@ -443,7 +443,7 @@ rio_mport_get_physefb(struct rio_mport *port, int local, | |||
| 443 | * @from is not %NULL, searches continue from next device on the global | 443 | * @from is not %NULL, searches continue from next device on the global |
| 444 | * list. | 444 | * list. |
| 445 | */ | 445 | */ |
| 446 | static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from) | 446 | struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from) |
| 447 | { | 447 | { |
| 448 | struct list_head *n; | 448 | struct list_head *n; |
| 449 | struct rio_dev *rdev; | 449 | struct rio_dev *rdev; |
| @@ -495,6 +495,232 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) | |||
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | /** | 497 | /** |
| 498 | * rio_chk_dev_route - Validate route to the specified device. | ||
| 499 | * @rdev: RIO device failed to respond | ||
| 500 | * @nrdev: Last active device on the route to rdev | ||
| 501 | * @npnum: nrdev's port number on the route to rdev | ||
| 502 | * | ||
| 503 | * Follows a route to the specified RIO device to determine the last available | ||
| 504 | * device (and corresponding RIO port) on the route. | ||
| 505 | */ | ||
| 506 | static int | ||
| 507 | rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) | ||
| 508 | { | ||
| 509 | u32 result; | ||
| 510 | int p_port, dstid, rc = -EIO; | ||
| 511 | struct rio_dev *prev = NULL; | ||
| 512 | |||
| 513 | /* Find switch with failed RIO link */ | ||
| 514 | while (rdev->prev && (rdev->prev->pef & RIO_PEF_SWITCH)) { | ||
| 515 | if (!rio_read_config_32(rdev->prev, RIO_DEV_ID_CAR, &result)) { | ||
| 516 | prev = rdev->prev; | ||
| 517 | break; | ||
| 518 | } | ||
| 519 | rdev = rdev->prev; | ||
| 520 | } | ||
| 521 | |||
| 522 | if (prev == NULL) | ||
| 523 | goto err_out; | ||
| 524 | |||
| 525 | dstid = (rdev->pef & RIO_PEF_SWITCH) ? | ||
| 526 | rdev->rswitch->destid : rdev->destid; | ||
| 527 | p_port = prev->rswitch->route_table[dstid]; | ||
| 528 | |||
| 529 | if (p_port != RIO_INVALID_ROUTE) { | ||
| 530 | pr_debug("RIO: link failed on [%s]-P%d\n", | ||
| 531 | rio_name(prev), p_port); | ||
| 532 | *nrdev = prev; | ||
| 533 | *npnum = p_port; | ||
| 534 | rc = 0; | ||
| 535 | } else | ||
| 536 | pr_debug("RIO: failed to trace route to %s\n", rio_name(rdev)); | ||
| 537 | err_out: | ||
| 538 | return rc; | ||
| 539 | } | ||
| 540 | |||
| 541 | /** | ||
| 542 | * rio_mport_chk_dev_access - Validate access to the specified device. | ||
| 543 | * @mport: Master port to send transactions | ||
| 544 | * @destid: Device destination ID in network | ||
| 545 | * @hopcount: Number of hops into the network | ||
| 546 | */ | ||
| 547 | int | ||
| 548 | rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount) | ||
| 549 | { | ||
| 550 | int i = 0; | ||
| 551 | u32 tmp; | ||
| 552 | |||
| 553 | while (rio_mport_read_config_32(mport, destid, hopcount, | ||
| 554 | RIO_DEV_ID_CAR, &tmp)) { | ||
| 555 | i++; | ||
| 556 | if (i == RIO_MAX_CHK_RETRY) | ||
| 557 | return -EIO; | ||
| 558 | mdelay(1); | ||
| 559 | } | ||
| 560 | |||
| 561 | return 0; | ||
| 562 | } | ||
| 563 | |||
| 564 | /** | ||
| 565 | * rio_chk_dev_access - Validate access to the specified device. | ||
| 566 | * @rdev: Pointer to RIO device control structure | ||
| 567 | */ | ||
| 568 | static int rio_chk_dev_access(struct rio_dev *rdev) | ||
| 569 | { | ||
| 570 | u8 hopcount = 0xff; | ||
| 571 | u16 destid = rdev->destid; | ||
| 572 | |||
| 573 | if (rdev->rswitch) { | ||
| 574 | destid = rdev->rswitch->destid; | ||
| 575 | hopcount = rdev->rswitch->hopcount; | ||
| 576 | } | ||
| 577 | |||
| 578 | return rio_mport_chk_dev_access(rdev->net->hport, destid, hopcount); | ||
| 579 | } | ||
| 580 | |||
| 581 | /** | ||
| 582 | * rio_get_input_status - Sends a Link-Request/Input-Status control symbol and | ||
| 583 | * returns link-response (if requested). | ||
| 584 | * @rdev: RIO devive to issue Input-status command | ||
| 585 | * @pnum: Device port number to issue the command | ||
| 586 | * @lnkresp: Response from a link partner | ||
| 587 | */ | ||
| 588 | static int | ||
| 589 | rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp) | ||
| 590 | { | ||
| 591 | struct rio_mport *mport = rdev->net->hport; | ||
| 592 | u16 destid = rdev->rswitch->destid; | ||
| 593 | u8 hopcount = rdev->rswitch->hopcount; | ||
| 594 | u32 regval; | ||
| 595 | int checkcount; | ||
| 596 | |||
| 597 | if (lnkresp) { | ||
| 598 | /* Read from link maintenance response register | ||
| 599 | * to clear valid bit */ | ||
| 600 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 601 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), | ||
| 602 | ®val); | ||
| 603 | udelay(50); | ||
| 604 | } | ||
| 605 | |||
| 606 | /* Issue Input-status command */ | ||
| 607 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 608 | rdev->phys_efptr + RIO_PORT_N_MNT_REQ_CSR(pnum), | ||
| 609 | RIO_MNT_REQ_CMD_IS); | ||
| 610 | |||
| 611 | /* Exit if the response is not expected */ | ||
| 612 | if (lnkresp == NULL) | ||
| 613 | return 0; | ||
| 614 | |||
| 615 | checkcount = 3; | ||
| 616 | while (checkcount--) { | ||
| 617 | udelay(50); | ||
| 618 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 619 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), | ||
| 620 | ®val); | ||
| 621 | if (regval & RIO_PORT_N_MNT_RSP_RVAL) { | ||
| 622 | *lnkresp = regval; | ||
| 623 | return 0; | ||
| 624 | } | ||
| 625 | } | ||
| 626 | |||
| 627 | return -EIO; | ||
| 628 | } | ||
| 629 | |||
| 630 | /** | ||
| 631 | * rio_clr_err_stopped - Clears port Error-stopped states. | ||
| 632 | * @rdev: Pointer to RIO device control structure | ||
| 633 | * @pnum: Switch port number to clear errors | ||
| 634 | * @err_status: port error status (if 0 reads register from device) | ||
| 635 | */ | ||
| 636 | static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) | ||
| 637 | { | ||
| 638 | struct rio_mport *mport = rdev->net->hport; | ||
| 639 | u16 destid = rdev->rswitch->destid; | ||
| 640 | u8 hopcount = rdev->rswitch->hopcount; | ||
| 641 | struct rio_dev *nextdev = rdev->rswitch->nextdev[pnum]; | ||
| 642 | u32 regval; | ||
| 643 | u32 far_ackid, far_linkstat, near_ackid; | ||
| 644 | |||
| 645 | if (err_status == 0) | ||
| 646 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 647 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), | ||
| 648 | &err_status); | ||
| 649 | |||
| 650 | if (err_status & RIO_PORT_N_ERR_STS_PW_OUT_ES) { | ||
| 651 | pr_debug("RIO_EM: servicing Output Error-Stopped state\n"); | ||
| 652 | /* | ||
| 653 | * Send a Link-Request/Input-Status control symbol | ||
| 654 | */ | ||
| 655 | if (rio_get_input_status(rdev, pnum, ®val)) { | ||
| 656 | pr_debug("RIO_EM: Input-status response timeout\n"); | ||
| 657 | goto rd_err; | ||
| 658 | } | ||
| 659 | |||
| 660 | pr_debug("RIO_EM: SP%d Input-status response=0x%08x\n", | ||
| 661 | pnum, regval); | ||
| 662 | far_ackid = (regval & RIO_PORT_N_MNT_RSP_ASTAT) >> 5; | ||
| 663 | far_linkstat = regval & RIO_PORT_N_MNT_RSP_LSTAT; | ||
| 664 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 665 | rdev->phys_efptr + RIO_PORT_N_ACK_STS_CSR(pnum), | ||
| 666 | ®val); | ||
| 667 | pr_debug("RIO_EM: SP%d_ACK_STS_CSR=0x%08x\n", pnum, regval); | ||
| 668 | near_ackid = (regval & RIO_PORT_N_ACK_INBOUND) >> 24; | ||
| 669 | pr_debug("RIO_EM: SP%d far_ackID=0x%02x far_linkstat=0x%02x" \ | ||
| 670 | " near_ackID=0x%02x\n", | ||
| 671 | pnum, far_ackid, far_linkstat, near_ackid); | ||
| 672 | |||
| 673 | /* | ||
| 674 | * If required, synchronize ackIDs of near and | ||
| 675 | * far sides. | ||
| 676 | */ | ||
| 677 | if ((far_ackid != ((regval & RIO_PORT_N_ACK_OUTSTAND) >> 8)) || | ||
| 678 | (far_ackid != (regval & RIO_PORT_N_ACK_OUTBOUND))) { | ||
| 679 | /* Align near outstanding/outbound ackIDs with | ||
| 680 | * far inbound. | ||
| 681 | */ | ||
| 682 | rio_mport_write_config_32(mport, destid, | ||
| 683 | hopcount, rdev->phys_efptr + | ||
| 684 | RIO_PORT_N_ACK_STS_CSR(pnum), | ||
| 685 | (near_ackid << 24) | | ||
| 686 | (far_ackid << 8) | far_ackid); | ||
| 687 | /* Align far outstanding/outbound ackIDs with | ||
| 688 | * near inbound. | ||
| 689 | */ | ||
| 690 | far_ackid++; | ||
| 691 | if (nextdev) | ||
| 692 | rio_write_config_32(nextdev, | ||
| 693 | nextdev->phys_efptr + | ||
| 694 | RIO_PORT_N_ACK_STS_CSR(RIO_GET_PORT_NUM(nextdev->swpinfo)), | ||
| 695 | (far_ackid << 24) | | ||
| 696 | (near_ackid << 8) | near_ackid); | ||
| 697 | else | ||
| 698 | pr_debug("RIO_EM: Invalid nextdev pointer (NULL)\n"); | ||
| 699 | } | ||
| 700 | rd_err: | ||
| 701 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 702 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), | ||
| 703 | &err_status); | ||
| 704 | pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status); | ||
| 705 | } | ||
| 706 | |||
| 707 | if ((err_status & RIO_PORT_N_ERR_STS_PW_INP_ES) && nextdev) { | ||
| 708 | pr_debug("RIO_EM: servicing Input Error-Stopped state\n"); | ||
| 709 | rio_get_input_status(nextdev, | ||
| 710 | RIO_GET_PORT_NUM(nextdev->swpinfo), NULL); | ||
| 711 | udelay(50); | ||
| 712 | |||
| 713 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 714 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), | ||
| 715 | &err_status); | ||
| 716 | pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status); | ||
| 717 | } | ||
| 718 | |||
| 719 | return (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES | | ||
| 720 | RIO_PORT_N_ERR_STS_PW_INP_ES)) ? 1 : 0; | ||
| 721 | } | ||
| 722 | |||
| 723 | /** | ||
| 498 | * rio_inb_pwrite_handler - process inbound port-write message | 724 | * rio_inb_pwrite_handler - process inbound port-write message |
| 499 | * @pw_msg: pointer to inbound port-write message | 725 | * @pw_msg: pointer to inbound port-write message |
| 500 | * | 726 | * |
| @@ -507,13 +733,13 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
| 507 | struct rio_mport *mport; | 733 | struct rio_mport *mport; |
| 508 | u8 hopcount; | 734 | u8 hopcount; |
| 509 | u16 destid; | 735 | u16 destid; |
| 510 | u32 err_status; | 736 | u32 err_status, em_perrdet, em_ltlerrdet; |
| 511 | int rc, portnum; | 737 | int rc, portnum; |
| 512 | 738 | ||
| 513 | rdev = rio_get_comptag(pw_msg->em.comptag, NULL); | 739 | rdev = rio_get_comptag(pw_msg->em.comptag, NULL); |
| 514 | if (rdev == NULL) { | 740 | if (rdev == NULL) { |
| 515 | /* Someting bad here (probably enumeration error) */ | 741 | /* Device removed or enumeration error */ |
| 516 | pr_err("RIO: %s No matching device for CTag 0x%08x\n", | 742 | pr_debug("RIO: %s No matching device for CTag 0x%08x\n", |
| 517 | __func__, pw_msg->em.comptag); | 743 | __func__, pw_msg->em.comptag); |
| 518 | return -EIO; | 744 | return -EIO; |
| 519 | } | 745 | } |
| @@ -524,12 +750,11 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
| 524 | { | 750 | { |
| 525 | u32 i; | 751 | u32 i; |
| 526 | for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) { | 752 | for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) { |
| 527 | pr_debug("0x%02x: %08x %08x %08x %08x", | 753 | pr_debug("0x%02x: %08x %08x %08x %08x\n", |
| 528 | i*4, pw_msg->raw[i], pw_msg->raw[i + 1], | 754 | i*4, pw_msg->raw[i], pw_msg->raw[i + 1], |
| 529 | pw_msg->raw[i + 2], pw_msg->raw[i + 3]); | 755 | pw_msg->raw[i + 2], pw_msg->raw[i + 3]); |
| 530 | i += 4; | 756 | i += 4; |
| 531 | } | 757 | } |
| 532 | pr_debug("\n"); | ||
| 533 | } | 758 | } |
| 534 | #endif | 759 | #endif |
| 535 | 760 | ||
| @@ -545,6 +770,26 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
| 545 | return 0; | 770 | return 0; |
| 546 | } | 771 | } |
| 547 | 772 | ||
| 773 | portnum = pw_msg->em.is_port & 0xFF; | ||
| 774 | |||
| 775 | /* Check if device and route to it are functional: | ||
| 776 | * Sometimes devices may send PW message(s) just before being | ||
| 777 | * powered down (or link being lost). | ||
| 778 | */ | ||
| 779 | if (rio_chk_dev_access(rdev)) { | ||
| 780 | pr_debug("RIO: device access failed - get link partner\n"); | ||
| 781 | /* Scan route to the device and identify failed link. | ||
| 782 | * This will replace device and port reported in PW message. | ||
| 783 | * PW message should not be used after this point. | ||
| 784 | */ | ||
| 785 | if (rio_chk_dev_route(rdev, &rdev, &portnum)) { | ||
| 786 | pr_err("RIO: Route trace for %s failed\n", | ||
| 787 | rio_name(rdev)); | ||
| 788 | return -EIO; | ||
| 789 | } | ||
| 790 | pw_msg = NULL; | ||
| 791 | } | ||
| 792 | |||
| 548 | /* For End-point devices processing stops here */ | 793 | /* For End-point devices processing stops here */ |
| 549 | if (!(rdev->pef & RIO_PEF_SWITCH)) | 794 | if (!(rdev->pef & RIO_PEF_SWITCH)) |
| 550 | return 0; | 795 | return 0; |
| @@ -562,9 +807,6 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
| 562 | /* | 807 | /* |
| 563 | * Process the port-write notification from switch | 808 | * Process the port-write notification from switch |
| 564 | */ | 809 | */ |
| 565 | |||
| 566 | portnum = pw_msg->em.is_port & 0xFF; | ||
| 567 | |||
| 568 | if (rdev->rswitch->em_handle) | 810 | if (rdev->rswitch->em_handle) |
| 569 | rdev->rswitch->em_handle(rdev, portnum); | 811 | rdev->rswitch->em_handle(rdev, portnum); |
| 570 | 812 | ||
| @@ -573,29 +815,28 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
| 573 | &err_status); | 815 | &err_status); |
| 574 | pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status); | 816 | pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status); |
| 575 | 817 | ||
| 576 | if (pw_msg->em.errdetect) { | 818 | if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) { |
| 577 | pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n", | ||
| 578 | portnum, pw_msg->em.errdetect); | ||
| 579 | /* Clear EM Port N Error Detect CSR */ | ||
| 580 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 581 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0); | ||
| 582 | } | ||
| 583 | 819 | ||
| 584 | if (pw_msg->em.ltlerrdet) { | 820 | if (!(rdev->rswitch->port_ok & (1 << portnum))) { |
| 585 | pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n", | 821 | rdev->rswitch->port_ok |= (1 << portnum); |
| 586 | pw_msg->em.ltlerrdet); | 822 | rio_set_port_lockout(rdev, portnum, 0); |
| 587 | /* Clear EM L/T Layer Error Detect CSR */ | 823 | /* Schedule Insertion Service */ |
| 588 | rio_mport_write_config_32(mport, destid, hopcount, | 824 | pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n", |
| 589 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0); | 825 | rio_name(rdev), portnum); |
| 590 | } | 826 | } |
| 591 | 827 | ||
| 592 | /* Clear Port Errors */ | 828 | /* Clear error-stopped states (if reported). |
| 593 | rio_mport_write_config_32(mport, destid, hopcount, | 829 | * Depending on the link partner state, two attempts |
| 594 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | 830 | * may be needed for successful recovery. |
| 595 | err_status & RIO_PORT_N_ERR_STS_CLR_MASK); | 831 | */ |
| 832 | if (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES | | ||
| 833 | RIO_PORT_N_ERR_STS_PW_INP_ES)) { | ||
| 834 | if (rio_clr_err_stopped(rdev, portnum, err_status)) | ||
| 835 | rio_clr_err_stopped(rdev, portnum, 0); | ||
| 836 | } | ||
| 837 | } else { /* if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) */ | ||
| 596 | 838 | ||
| 597 | if (rdev->rswitch->port_ok & (1 << portnum)) { | 839 | if (rdev->rswitch->port_ok & (1 << portnum)) { |
| 598 | if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) { | ||
| 599 | rdev->rswitch->port_ok &= ~(1 << portnum); | 840 | rdev->rswitch->port_ok &= ~(1 << portnum); |
| 600 | rio_set_port_lockout(rdev, portnum, 1); | 841 | rio_set_port_lockout(rdev, portnum, 1); |
| 601 | 842 | ||
| @@ -608,21 +849,32 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
| 608 | pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n", | 849 | pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n", |
| 609 | rio_name(rdev), portnum); | 850 | rio_name(rdev), portnum); |
| 610 | } | 851 | } |
| 611 | } else { | 852 | } |
| 612 | if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) { | ||
| 613 | rdev->rswitch->port_ok |= (1 << portnum); | ||
| 614 | rio_set_port_lockout(rdev, portnum, 0); | ||
| 615 | 853 | ||
| 616 | /* Schedule Insertion Service */ | 854 | rio_mport_read_config_32(mport, destid, hopcount, |
| 617 | pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n", | 855 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet); |
| 618 | rio_name(rdev), portnum); | 856 | if (em_perrdet) { |
| 619 | } | 857 | pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n", |
| 858 | portnum, em_perrdet); | ||
| 859 | /* Clear EM Port N Error Detect CSR */ | ||
| 860 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 861 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0); | ||
| 862 | } | ||
| 863 | |||
| 864 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 865 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet); | ||
| 866 | if (em_ltlerrdet) { | ||
| 867 | pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n", | ||
| 868 | em_ltlerrdet); | ||
| 869 | /* Clear EM L/T Layer Error Detect CSR */ | ||
| 870 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 871 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0); | ||
| 620 | } | 872 | } |
| 621 | 873 | ||
| 622 | /* Clear Port-Write Pending bit */ | 874 | /* Clear remaining error bits and Port-Write Pending bit */ |
| 623 | rio_mport_write_config_32(mport, destid, hopcount, | 875 | rio_mport_write_config_32(mport, destid, hopcount, |
| 624 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | 876 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), |
| 625 | RIO_PORT_N_ERR_STS_PW_PEND); | 877 | err_status); |
| 626 | 878 | ||
| 627 | return 0; | 879 | return 0; |
| 628 | } | 880 | } |
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index f27b7a9c47d2..b1af414f15e6 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
| 15 | #include <linux/rio.h> | 15 | #include <linux/rio.h> |
| 16 | 16 | ||
| 17 | #define RIO_MAX_CHK_RETRY 3 | ||
| 18 | |||
| 17 | /* Functions internal to the RIO core code */ | 19 | /* Functions internal to the RIO core code */ |
| 18 | 20 | ||
| 19 | extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, | 21 | extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, |
| @@ -22,6 +24,8 @@ extern u32 rio_mport_get_physefb(struct rio_mport *port, int local, | |||
| 22 | u16 destid, u8 hopcount); | 24 | u16 destid, u8 hopcount); |
| 23 | extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, | 25 | extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, |
| 24 | u8 hopcount, u32 from); | 26 | u8 hopcount, u32 from); |
| 27 | extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, | ||
| 28 | u8 hopcount); | ||
| 25 | extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); | 29 | extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); |
| 26 | extern int rio_enum_mport(struct rio_mport *mport); | 30 | extern int rio_enum_mport(struct rio_mport *mport); |
| 27 | extern int rio_disc_mport(struct rio_mport *mport); | 31 | extern int rio_disc_mport(struct rio_mport *mport); |
| @@ -34,6 +38,7 @@ extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, | |||
| 34 | extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, | 38 | extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, |
| 35 | u8 hopcount, u16 table); | 39 | u8 hopcount, u16 table); |
| 36 | extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); | 40 | extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); |
| 41 | extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from); | ||
| 37 | 42 | ||
| 38 | /* Structures internal to the RIO core code */ | 43 | /* Structures internal to the RIO core code */ |
| 39 | extern struct device_attribute rio_dev_attrs[]; | 44 | extern struct device_attribute rio_dev_attrs[]; |
diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig index 2b4e9b2b6631..f47fee5d4563 100644 --- a/drivers/rapidio/switches/Kconfig +++ b/drivers/rapidio/switches/Kconfig | |||
| @@ -20,6 +20,13 @@ config RAPIDIO_TSI568 | |||
| 20 | ---help--- | 20 | ---help--- |
| 21 | Includes support for IDT Tsi568 serial RapidIO switch. | 21 | Includes support for IDT Tsi568 serial RapidIO switch. |
| 22 | 22 | ||
| 23 | config RAPIDIO_CPS_GEN2 | ||
| 24 | bool "IDT CPS Gen.2 SRIO switch support" | ||
| 25 | depends on RAPIDIO | ||
| 26 | default n | ||
| 27 | ---help--- | ||
| 28 | Includes support for ITD CPS Gen.2 serial RapidIO switches. | ||
| 29 | |||
| 23 | config RAPIDIO_TSI500 | 30 | config RAPIDIO_TSI500 |
| 24 | bool "Tsi500 Parallel RapidIO switch support" | 31 | bool "Tsi500 Parallel RapidIO switch support" |
| 25 | depends on RAPIDIO | 32 | depends on RAPIDIO |
diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile index fe4adc3e8d5f..48d67a6b98c8 100644 --- a/drivers/rapidio/switches/Makefile +++ b/drivers/rapidio/switches/Makefile | |||
| @@ -6,6 +6,7 @@ obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o | |||
| 6 | obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o | 6 | obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o |
| 7 | obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o | 7 | obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o |
| 8 | obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o | 8 | obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o |
| 9 | obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o | ||
| 9 | 10 | ||
| 10 | ifeq ($(CONFIG_RAPIDIO_DEBUG),y) | 11 | ifeq ($(CONFIG_RAPIDIO_DEBUG),y) |
| 11 | EXTRA_CFLAGS += -DDEBUG | 12 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c new file mode 100644 index 000000000000..0bb871cb5c40 --- /dev/null +++ b/drivers/rapidio/switches/idt_gen2.c | |||
| @@ -0,0 +1,447 @@ | |||
| 1 | /* | ||
| 2 | * IDT CPS Gen.2 Serial RapidIO switch family support | ||
| 3 | * | ||
| 4 | * Copyright 2010 Integrated Device Technology, Inc. | ||
| 5 | * Alexandre Bounine <alexandre.bounine@idt.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/rio.h> | ||
| 14 | #include <linux/rio_drv.h> | ||
| 15 | #include <linux/rio_ids.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include "../rio.h" | ||
| 18 | |||
| 19 | #define LOCAL_RTE_CONF_DESTID_SEL 0x010070 | ||
| 20 | #define LOCAL_RTE_CONF_DESTID_SEL_PSEL 0x0000001f | ||
| 21 | |||
| 22 | #define IDT_LT_ERR_REPORT_EN 0x03100c | ||
| 23 | |||
| 24 | #define IDT_PORT_ERR_REPORT_EN(n) (0x031044 + (n)*0x40) | ||
| 25 | #define IDT_PORT_ERR_REPORT_EN_BC 0x03ff04 | ||
| 26 | |||
| 27 | #define IDT_PORT_ISERR_REPORT_EN(n) (0x03104C + (n)*0x40) | ||
| 28 | #define IDT_PORT_ISERR_REPORT_EN_BC 0x03ff0c | ||
| 29 | #define IDT_PORT_INIT_TX_ACQUIRED 0x00000020 | ||
| 30 | |||
| 31 | #define IDT_LANE_ERR_REPORT_EN(n) (0x038010 + (n)*0x100) | ||
| 32 | #define IDT_LANE_ERR_REPORT_EN_BC 0x03ff10 | ||
| 33 | |||
| 34 | #define IDT_DEV_CTRL_1 0xf2000c | ||
| 35 | #define IDT_DEV_CTRL_1_GENPW 0x02000000 | ||
| 36 | #define IDT_DEV_CTRL_1_PRSTBEH 0x00000001 | ||
| 37 | |||
| 38 | #define IDT_CFGBLK_ERR_CAPTURE_EN 0x020008 | ||
| 39 | #define IDT_CFGBLK_ERR_REPORT 0xf20014 | ||
| 40 | #define IDT_CFGBLK_ERR_REPORT_GENPW 0x00000002 | ||
| 41 | |||
| 42 | #define IDT_AUX_PORT_ERR_CAP_EN 0x020000 | ||
| 43 | #define IDT_AUX_ERR_REPORT_EN 0xf20018 | ||
| 44 | #define IDT_AUX_PORT_ERR_LOG_I2C 0x00000002 | ||
| 45 | #define IDT_AUX_PORT_ERR_LOG_JTAG 0x00000001 | ||
| 46 | |||
| 47 | #define IDT_ISLTL_ADDRESS_CAP 0x021014 | ||
| 48 | |||
| 49 | #define IDT_RIO_DOMAIN 0xf20020 | ||
| 50 | #define IDT_RIO_DOMAIN_MASK 0x000000ff | ||
| 51 | |||
| 52 | #define IDT_PW_INFO_CSR 0xf20024 | ||
| 53 | |||
| 54 | #define IDT_SOFT_RESET 0xf20040 | ||
| 55 | #define IDT_SOFT_RESET_REQ 0x00030097 | ||
| 56 | |||
| 57 | #define IDT_I2C_MCTRL 0xf20050 | ||
| 58 | #define IDT_I2C_MCTRL_GENPW 0x04000000 | ||
| 59 | |||
| 60 | #define IDT_JTAG_CTRL 0xf2005c | ||
| 61 | #define IDT_JTAG_CTRL_GENPW 0x00000002 | ||
| 62 | |||
| 63 | #define IDT_LANE_CTRL(n) (0xff8000 + (n)*0x100) | ||
| 64 | #define IDT_LANE_CTRL_BC 0xffff00 | ||
| 65 | #define IDT_LANE_CTRL_GENPW 0x00200000 | ||
| 66 | #define IDT_LANE_DFE_1_BC 0xffff18 | ||
| 67 | #define IDT_LANE_DFE_2_BC 0xffff1c | ||
| 68 | |||
| 69 | #define IDT_PORT_OPS(n) (0xf40004 + (n)*0x100) | ||
| 70 | #define IDT_PORT_OPS_GENPW 0x08000000 | ||
| 71 | #define IDT_PORT_OPS_PL_ELOG 0x00000040 | ||
| 72 | #define IDT_PORT_OPS_LL_ELOG 0x00000020 | ||
| 73 | #define IDT_PORT_OPS_LT_ELOG 0x00000010 | ||
| 74 | #define IDT_PORT_OPS_BC 0xf4ff04 | ||
| 75 | |||
| 76 | #define IDT_PORT_ISERR_DET(n) (0xf40008 + (n)*0x100) | ||
| 77 | |||
| 78 | #define IDT_ERR_CAP 0xfd0000 | ||
| 79 | #define IDT_ERR_CAP_LOG_OVERWR 0x00000004 | ||
| 80 | |||
| 81 | #define IDT_ERR_RD 0xfd0004 | ||
| 82 | |||
| 83 | #define IDT_DEFAULT_ROUTE 0xde | ||
| 84 | #define IDT_NO_ROUTE 0xdf | ||
| 85 | |||
| 86 | static int | ||
| 87 | idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
| 88 | u16 table, u16 route_destid, u8 route_port) | ||
| 89 | { | ||
| 90 | /* | ||
| 91 | * Select routing table to update | ||
| 92 | */ | ||
| 93 | if (table == RIO_GLOBAL_TABLE) | ||
| 94 | table = 0; | ||
| 95 | else | ||
| 96 | table++; | ||
| 97 | |||
| 98 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 99 | LOCAL_RTE_CONF_DESTID_SEL, table); | ||
| 100 | |||
| 101 | /* | ||
| 102 | * Program destination port for the specified destID | ||
| 103 | */ | ||
| 104 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 105 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, | ||
| 106 | (u32)route_destid); | ||
| 107 | |||
| 108 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 109 | RIO_STD_RTE_CONF_PORT_SEL_CSR, | ||
| 110 | (u32)route_port); | ||
| 111 | udelay(10); | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int | ||
| 117 | idtg2_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
| 118 | u16 table, u16 route_destid, u8 *route_port) | ||
| 119 | { | ||
| 120 | u32 result; | ||
| 121 | |||
| 122 | /* | ||
| 123 | * Select routing table to read | ||
| 124 | */ | ||
| 125 | if (table == RIO_GLOBAL_TABLE) | ||
| 126 | table = 0; | ||
| 127 | else | ||
| 128 | table++; | ||
| 129 | |||
| 130 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 131 | LOCAL_RTE_CONF_DESTID_SEL, table); | ||
| 132 | |||
| 133 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 134 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, | ||
| 135 | route_destid); | ||
| 136 | |||
| 137 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 138 | RIO_STD_RTE_CONF_PORT_SEL_CSR, &result); | ||
| 139 | |||
| 140 | if (IDT_DEFAULT_ROUTE == (u8)result || IDT_NO_ROUTE == (u8)result) | ||
| 141 | *route_port = RIO_INVALID_ROUTE; | ||
| 142 | else | ||
| 143 | *route_port = (u8)result; | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int | ||
| 149 | idtg2_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
| 150 | u16 table) | ||
| 151 | { | ||
| 152 | u32 i; | ||
| 153 | |||
| 154 | /* | ||
| 155 | * Select routing table to read | ||
| 156 | */ | ||
| 157 | if (table == RIO_GLOBAL_TABLE) | ||
| 158 | table = 0; | ||
| 159 | else | ||
| 160 | table++; | ||
| 161 | |||
| 162 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 163 | LOCAL_RTE_CONF_DESTID_SEL, table); | ||
| 164 | |||
| 165 | for (i = RIO_STD_RTE_CONF_EXTCFGEN; | ||
| 166 | i <= (RIO_STD_RTE_CONF_EXTCFGEN | 0xff);) { | ||
| 167 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 168 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, i); | ||
| 169 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 170 | RIO_STD_RTE_CONF_PORT_SEL_CSR, | ||
| 171 | (IDT_DEFAULT_ROUTE << 24) | (IDT_DEFAULT_ROUTE << 16) | | ||
| 172 | (IDT_DEFAULT_ROUTE << 8) | IDT_DEFAULT_ROUTE); | ||
| 173 | i += 4; | ||
| 174 | } | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | |||
| 180 | static int | ||
| 181 | idtg2_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
| 182 | u8 sw_domain) | ||
| 183 | { | ||
| 184 | /* | ||
| 185 | * Switch domain configuration operates only at global level | ||
| 186 | */ | ||
| 187 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 188 | IDT_RIO_DOMAIN, (u32)sw_domain); | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int | ||
| 193 | idtg2_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
| 194 | u8 *sw_domain) | ||
| 195 | { | ||
| 196 | u32 regval; | ||
| 197 | |||
| 198 | /* | ||
| 199 | * Switch domain configuration operates only at global level | ||
| 200 | */ | ||
| 201 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 202 | IDT_RIO_DOMAIN, ®val); | ||
| 203 | |||
| 204 | *sw_domain = (u8)(regval & 0xff); | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int | ||
| 210 | idtg2_em_init(struct rio_dev *rdev) | ||
| 211 | { | ||
| 212 | struct rio_mport *mport = rdev->net->hport; | ||
| 213 | u16 destid = rdev->rswitch->destid; | ||
| 214 | u8 hopcount = rdev->rswitch->hopcount; | ||
| 215 | u32 regval; | ||
| 216 | int i, tmp; | ||
| 217 | |||
| 218 | /* | ||
| 219 | * This routine performs device-specific initialization only. | ||
| 220 | * All standard EM configuration should be performed at upper level. | ||
| 221 | */ | ||
| 222 | |||
| 223 | pr_debug("RIO: %s [%d:%d]\n", __func__, destid, hopcount); | ||
| 224 | |||
| 225 | /* Set Port-Write info CSR: PRIO=3 and CRF=1 */ | ||
| 226 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 227 | IDT_PW_INFO_CSR, 0x0000e000); | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Configure LT LAYER error reporting. | ||
| 231 | */ | ||
| 232 | |||
| 233 | /* Enable standard (RIO.p8) error reporting */ | ||
| 234 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 235 | IDT_LT_ERR_REPORT_EN, | ||
| 236 | REM_LTL_ERR_ILLTRAN | REM_LTL_ERR_UNSOLR | | ||
| 237 | REM_LTL_ERR_UNSUPTR); | ||
| 238 | |||
| 239 | /* Use Port-Writes for LT layer error reporting. | ||
| 240 | * Enable per-port reset | ||
| 241 | */ | ||
| 242 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 243 | IDT_DEV_CTRL_1, ®val); | ||
| 244 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 245 | IDT_DEV_CTRL_1, | ||
| 246 | regval | IDT_DEV_CTRL_1_GENPW | IDT_DEV_CTRL_1_PRSTBEH); | ||
| 247 | |||
| 248 | /* | ||
| 249 | * Configure PORT error reporting. | ||
| 250 | */ | ||
| 251 | |||
| 252 | /* Report all RIO.p8 errors supported by device */ | ||
| 253 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 254 | IDT_PORT_ERR_REPORT_EN_BC, 0x807e8037); | ||
| 255 | |||
| 256 | /* Configure reporting of implementation specific errors/events */ | ||
| 257 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 258 | IDT_PORT_ISERR_REPORT_EN_BC, IDT_PORT_INIT_TX_ACQUIRED); | ||
| 259 | |||
| 260 | /* Use Port-Writes for port error reporting and enable error logging */ | ||
| 261 | tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo); | ||
| 262 | for (i = 0; i < tmp; i++) { | ||
| 263 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 264 | IDT_PORT_OPS(i), ®val); | ||
| 265 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 266 | IDT_PORT_OPS(i), regval | IDT_PORT_OPS_GENPW | | ||
| 267 | IDT_PORT_OPS_PL_ELOG | | ||
| 268 | IDT_PORT_OPS_LL_ELOG | | ||
| 269 | IDT_PORT_OPS_LT_ELOG); | ||
| 270 | } | ||
| 271 | /* Overwrite error log if full */ | ||
| 272 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 273 | IDT_ERR_CAP, IDT_ERR_CAP_LOG_OVERWR); | ||
| 274 | |||
| 275 | /* | ||
| 276 | * Configure LANE error reporting. | ||
| 277 | */ | ||
| 278 | |||
| 279 | /* Disable line error reporting */ | ||
| 280 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 281 | IDT_LANE_ERR_REPORT_EN_BC, 0); | ||
| 282 | |||
| 283 | /* Use Port-Writes for lane error reporting (when enabled) | ||
| 284 | * (do per-lane update because lanes may have different configuration) | ||
| 285 | */ | ||
| 286 | tmp = (rdev->did == RIO_DID_IDTCPS1848) ? 48 : 16; | ||
| 287 | for (i = 0; i < tmp; i++) { | ||
| 288 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 289 | IDT_LANE_CTRL(i), ®val); | ||
| 290 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 291 | IDT_LANE_CTRL(i), regval | IDT_LANE_CTRL_GENPW); | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * Configure AUX error reporting. | ||
| 296 | */ | ||
| 297 | |||
| 298 | /* Disable JTAG and I2C Error capture */ | ||
| 299 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 300 | IDT_AUX_PORT_ERR_CAP_EN, 0); | ||
| 301 | |||
| 302 | /* Disable JTAG and I2C Error reporting/logging */ | ||
| 303 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 304 | IDT_AUX_ERR_REPORT_EN, 0); | ||
| 305 | |||
| 306 | /* Disable Port-Write notification from JTAG */ | ||
| 307 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 308 | IDT_JTAG_CTRL, 0); | ||
| 309 | |||
| 310 | /* Disable Port-Write notification from I2C */ | ||
| 311 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 312 | IDT_I2C_MCTRL, ®val); | ||
| 313 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 314 | IDT_I2C_MCTRL, | ||
| 315 | regval & ~IDT_I2C_MCTRL_GENPW); | ||
| 316 | |||
| 317 | /* | ||
| 318 | * Configure CFG_BLK error reporting. | ||
| 319 | */ | ||
| 320 | |||
| 321 | /* Disable Configuration Block error capture */ | ||
| 322 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 323 | IDT_CFGBLK_ERR_CAPTURE_EN, 0); | ||
| 324 | |||
| 325 | /* Disable Port-Writes for Configuration Block error reporting */ | ||
| 326 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 327 | IDT_CFGBLK_ERR_REPORT, ®val); | ||
| 328 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 329 | IDT_CFGBLK_ERR_REPORT, | ||
| 330 | regval & ~IDT_CFGBLK_ERR_REPORT_GENPW); | ||
| 331 | |||
| 332 | /* set TVAL = ~50us */ | ||
| 333 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 334 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); | ||
| 335 | |||
| 336 | return 0; | ||
| 337 | } | ||
| 338 | |||
| 339 | static int | ||
| 340 | idtg2_em_handler(struct rio_dev *rdev, u8 portnum) | ||
| 341 | { | ||
| 342 | struct rio_mport *mport = rdev->net->hport; | ||
| 343 | u16 destid = rdev->rswitch->destid; | ||
| 344 | u8 hopcount = rdev->rswitch->hopcount; | ||
| 345 | u32 regval, em_perrdet, em_ltlerrdet; | ||
| 346 | |||
| 347 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 348 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet); | ||
| 349 | if (em_ltlerrdet) { | ||
| 350 | /* Service Logical/Transport Layer Error(s) */ | ||
| 351 | if (em_ltlerrdet & REM_LTL_ERR_IMPSPEC) { | ||
| 352 | /* Implementation specific error reported */ | ||
| 353 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 354 | IDT_ISLTL_ADDRESS_CAP, ®val); | ||
| 355 | |||
| 356 | pr_debug("RIO: %s Implementation Specific LTL errors" \ | ||
| 357 | " 0x%x @(0x%x)\n", | ||
| 358 | rio_name(rdev), em_ltlerrdet, regval); | ||
| 359 | |||
| 360 | /* Clear implementation specific address capture CSR */ | ||
| 361 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 362 | IDT_ISLTL_ADDRESS_CAP, 0); | ||
| 363 | |||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 368 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet); | ||
| 369 | if (em_perrdet) { | ||
| 370 | /* Service Port-Level Error(s) */ | ||
| 371 | if (em_perrdet & REM_PED_IMPL_SPEC) { | ||
| 372 | /* Implementation Specific port error reported */ | ||
| 373 | |||
| 374 | /* Get IS errors reported */ | ||
| 375 | rio_mport_read_config_32(mport, destid, hopcount, | ||
| 376 | IDT_PORT_ISERR_DET(portnum), ®val); | ||
| 377 | |||
| 378 | pr_debug("RIO: %s Implementation Specific Port" \ | ||
| 379 | " errors 0x%x\n", rio_name(rdev), regval); | ||
| 380 | |||
| 381 | /* Clear all implementation specific events */ | ||
| 382 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 383 | IDT_PORT_ISERR_DET(portnum), 0); | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | static ssize_t | ||
| 391 | idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 392 | { | ||
| 393 | struct rio_dev *rdev = to_rio_dev(dev); | ||
| 394 | struct rio_mport *mport = rdev->net->hport; | ||
| 395 | u16 destid = rdev->rswitch->destid; | ||
| 396 | u8 hopcount = rdev->rswitch->hopcount; | ||
| 397 | ssize_t len = 0; | ||
| 398 | u32 regval; | ||
| 399 | |||
| 400 | while (!rio_mport_read_config_32(mport, destid, hopcount, | ||
| 401 | IDT_ERR_RD, ®val)) { | ||
| 402 | if (!regval) /* 0 = end of log */ | ||
| 403 | break; | ||
| 404 | len += snprintf(buf + len, PAGE_SIZE - len, | ||
| 405 | "%08x\n", regval); | ||
| 406 | if (len >= (PAGE_SIZE - 10)) | ||
| 407 | break; | ||
| 408 | } | ||
| 409 | |||
| 410 | return len; | ||
| 411 | } | ||
| 412 | |||
| 413 | static DEVICE_ATTR(errlog, S_IRUGO, idtg2_show_errlog, NULL); | ||
| 414 | |||
| 415 | static int idtg2_sysfs(struct rio_dev *rdev, int create) | ||
| 416 | { | ||
| 417 | struct device *dev = &rdev->dev; | ||
| 418 | int err = 0; | ||
| 419 | |||
| 420 | if (create == RIO_SW_SYSFS_CREATE) { | ||
| 421 | /* Initialize sysfs entries */ | ||
| 422 | err = device_create_file(dev, &dev_attr_errlog); | ||
| 423 | if (err) | ||
| 424 | dev_err(dev, "Unable create sysfs errlog file\n"); | ||
| 425 | } else | ||
| 426 | device_remove_file(dev, &dev_attr_errlog); | ||
| 427 | |||
| 428 | return err; | ||
| 429 | } | ||
| 430 | |||
| 431 | static int idtg2_switch_init(struct rio_dev *rdev, int do_enum) | ||
| 432 | { | ||
| 433 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); | ||
| 434 | rdev->rswitch->add_entry = idtg2_route_add_entry; | ||
| 435 | rdev->rswitch->get_entry = idtg2_route_get_entry; | ||
| 436 | rdev->rswitch->clr_table = idtg2_route_clr_table; | ||
| 437 | rdev->rswitch->set_domain = idtg2_set_domain; | ||
| 438 | rdev->rswitch->get_domain = idtg2_get_domain; | ||
| 439 | rdev->rswitch->em_init = idtg2_em_init; | ||
| 440 | rdev->rswitch->em_handle = idtg2_em_handler; | ||
| 441 | rdev->rswitch->sw_sysfs = idtg2_sysfs; | ||
| 442 | |||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init); | ||
| 447 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init); | ||
diff --git a/drivers/rapidio/switches/idtcps.c b/drivers/rapidio/switches/idtcps.c index 2c790c144f89..fc9f6374f759 100644 --- a/drivers/rapidio/switches/idtcps.c +++ b/drivers/rapidio/switches/idtcps.c | |||
| @@ -117,6 +117,10 @@ idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
| 117 | 117 | ||
| 118 | static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) | 118 | static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) |
| 119 | { | 119 | { |
| 120 | struct rio_mport *mport = rdev->net->hport; | ||
| 121 | u16 destid = rdev->rswitch->destid; | ||
| 122 | u8 hopcount = rdev->rswitch->hopcount; | ||
| 123 | |||
| 120 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); | 124 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); |
| 121 | rdev->rswitch->add_entry = idtcps_route_add_entry; | 125 | rdev->rswitch->add_entry = idtcps_route_add_entry; |
| 122 | rdev->rswitch->get_entry = idtcps_route_get_entry; | 126 | rdev->rswitch->get_entry = idtcps_route_get_entry; |
| @@ -126,6 +130,12 @@ static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) | |||
| 126 | rdev->rswitch->em_init = NULL; | 130 | rdev->rswitch->em_init = NULL; |
| 127 | rdev->rswitch->em_handle = NULL; | 131 | rdev->rswitch->em_handle = NULL; |
| 128 | 132 | ||
| 133 | if (do_enum) { | ||
| 134 | /* set TVAL = ~50us */ | ||
| 135 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 136 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); | ||
| 137 | } | ||
| 138 | |||
| 129 | return 0; | 139 | return 0; |
| 130 | } | 140 | } |
| 131 | 141 | ||
diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c index f7fd7898606e..b9a389b9f812 100644 --- a/drivers/rapidio/switches/tsi568.c +++ b/drivers/rapidio/switches/tsi568.c | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | #define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n) | 29 | #define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n) |
| 30 | #define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n) | 30 | #define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n) |
| 31 | 31 | ||
| 32 | #define TSI568_SP_MODE_BC 0x10004 | 32 | #define TSI568_SP_MODE(n) (0x11004 + 0x100*n) |
| 33 | #define TSI568_SP_MODE_PW_DIS 0x08000000 | 33 | #define TSI568_SP_MODE_PW_DIS 0x08000000 |
| 34 | 34 | ||
| 35 | static int | 35 | static int |
| @@ -117,14 +117,19 @@ tsi568_em_init(struct rio_dev *rdev) | |||
| 117 | u16 destid = rdev->rswitch->destid; | 117 | u16 destid = rdev->rswitch->destid; |
| 118 | u8 hopcount = rdev->rswitch->hopcount; | 118 | u8 hopcount = rdev->rswitch->hopcount; |
| 119 | u32 regval; | 119 | u32 regval; |
| 120 | int portnum; | ||
| 120 | 121 | ||
| 121 | pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount); | 122 | pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount); |
| 122 | 123 | ||
| 123 | /* Make sure that Port-Writes are disabled (for all ports) */ | 124 | /* Make sure that Port-Writes are disabled (for all ports) */ |
| 124 | rio_mport_read_config_32(mport, destid, hopcount, | 125 | for (portnum = 0; |
| 125 | TSI568_SP_MODE_BC, ®val); | 126 | portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { |
| 126 | rio_mport_write_config_32(mport, destid, hopcount, | 127 | rio_mport_read_config_32(mport, destid, hopcount, |
| 127 | TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS); | 128 | TSI568_SP_MODE(portnum), ®val); |
| 129 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 130 | TSI568_SP_MODE(portnum), | ||
| 131 | regval | TSI568_SP_MODE_PW_DIS); | ||
| 132 | } | ||
| 128 | 133 | ||
| 129 | return 0; | 134 | return 0; |
| 130 | } | 135 | } |
diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c index d34df722d95f..2003fb63c404 100644 --- a/drivers/rapidio/switches/tsi57x.c +++ b/drivers/rapidio/switches/tsi57x.c | |||
| @@ -166,7 +166,8 @@ tsi57x_em_init(struct rio_dev *rdev) | |||
| 166 | 166 | ||
| 167 | pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount); | 167 | pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount); |
| 168 | 168 | ||
| 169 | for (portnum = 0; portnum < 16; portnum++) { | 169 | for (portnum = 0; |
| 170 | portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { | ||
| 170 | /* Make sure that Port-Writes are enabled (for all ports) */ | 171 | /* Make sure that Port-Writes are enabled (for all ports) */ |
| 171 | rio_mport_read_config_32(mport, destid, hopcount, | 172 | rio_mport_read_config_32(mport, destid, hopcount, |
| 172 | TSI578_SP_MODE(portnum), ®val); | 173 | TSI578_SP_MODE(portnum), ®val); |
| @@ -205,6 +206,10 @@ tsi57x_em_init(struct rio_dev *rdev) | |||
| 205 | portnum++; | 206 | portnum++; |
| 206 | } | 207 | } |
| 207 | 208 | ||
| 209 | /* set TVAL = ~50us */ | ||
| 210 | rio_mport_write_config_32(mport, destid, hopcount, | ||
| 211 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x9a << 8); | ||
| 212 | |||
| 208 | return 0; | 213 | return 0; |
| 209 | } | 214 | } |
| 210 | 215 | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 2785a0f16c9f..6a77437d4f5a 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -171,7 +171,8 @@ config RTC_DRV_DS3232 | |||
| 171 | depends on RTC_CLASS && I2C | 171 | depends on RTC_CLASS && I2C |
| 172 | help | 172 | help |
| 173 | If you say yes here you get support for Dallas Semiconductor | 173 | If you say yes here you get support for Dallas Semiconductor |
| 174 | DS3232 real-time clock chips. | 174 | DS3232 real-time clock chips. If an interrupt is associated |
| 175 | with the device, the alarm functionality is supported. | ||
| 175 | 176 | ||
| 176 | This driver can also be built as a module. If so, the module | 177 | This driver can also be built as a module. If so, the module |
| 177 | will be called rtc-ds3232. | 178 | will be called rtc-ds3232. |
| @@ -952,4 +953,13 @@ config RTC_DRV_JZ4740 | |||
| 952 | This driver can also be buillt as a module. If so, the module | 953 | This driver can also be buillt as a module. If so, the module |
| 953 | will be called rtc-jz4740. | 954 | will be called rtc-jz4740. |
| 954 | 955 | ||
| 956 | config RTC_DRV_LPC32XX | ||
| 957 | depends on ARCH_LPC32XX | ||
| 958 | tristate "NXP LPC32XX RTC" | ||
| 959 | help | ||
| 960 | This enables support for the NXP RTC in the LPC32XX | ||
| 961 | |||
| 962 | This driver can also be buillt as a module. If so, the module | ||
| 963 | will be called rtc-lpc32xx. | ||
| 964 | |||
| 955 | endif # RTC_CLASS | 965 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0f207b3b5833..7a7cb3228a1d 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -51,6 +51,7 @@ obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o | |||
| 51 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 51 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
| 52 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | 52 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o |
| 53 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | 53 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o |
| 54 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o | ||
| 54 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 55 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
| 55 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 56 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
| 56 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | 57 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 565562ba6ac9..e6539cbabb35 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -158,8 +158,10 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
| 158 | rtc_dev_prepare(rtc); | 158 | rtc_dev_prepare(rtc); |
| 159 | 159 | ||
| 160 | err = device_register(&rtc->dev); | 160 | err = device_register(&rtc->dev); |
| 161 | if (err) | 161 | if (err) { |
| 162 | put_device(&rtc->dev); | ||
| 162 | goto exit_kfree; | 163 | goto exit_kfree; |
| 164 | } | ||
| 163 | 165 | ||
| 164 | rtc_dev_add_device(rtc); | 166 | rtc_dev_add_device(rtc); |
| 165 | rtc_sysfs_add_device(rtc); | 167 | rtc_sysfs_add_device(rtc); |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index d4fb82d85e9b..b4b6087f2234 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
| 3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x | 3 | * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x |
| 4 | * | 4 | * |
| 5 | * Copyright 2004-2009 Analog Devices Inc. | 5 | * Copyright 2004-2010 Analog Devices Inc. |
| 6 | * | 6 | * |
| 7 | * Enter bugs at http://blackfin.uclinux.org/ | 7 | * Enter bugs at http://blackfin.uclinux.org/ |
| 8 | * | 8 | * |
| @@ -183,29 +183,33 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
| 183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 183 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
| 184 | unsigned long events = 0; | 184 | unsigned long events = 0; |
| 185 | bool write_complete = false; | 185 | bool write_complete = false; |
| 186 | u16 rtc_istat, rtc_ictl; | 186 | u16 rtc_istat, rtc_istat_clear, rtc_ictl, bits; |
| 187 | 187 | ||
| 188 | dev_dbg_stamp(dev); | 188 | dev_dbg_stamp(dev); |
| 189 | 189 | ||
| 190 | rtc_istat = bfin_read_RTC_ISTAT(); | 190 | rtc_istat = bfin_read_RTC_ISTAT(); |
| 191 | rtc_ictl = bfin_read_RTC_ICTL(); | 191 | rtc_ictl = bfin_read_RTC_ICTL(); |
| 192 | rtc_istat_clear = 0; | ||
| 192 | 193 | ||
| 193 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { | 194 | bits = RTC_ISTAT_WRITE_COMPLETE; |
| 194 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 195 | if (rtc_istat & bits) { |
| 196 | rtc_istat_clear |= bits; | ||
| 195 | write_complete = true; | 197 | write_complete = true; |
| 196 | complete(&bfin_write_complete); | 198 | complete(&bfin_write_complete); |
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 201 | bits = (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
| 200 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 202 | if (rtc_ictl & bits) { |
| 201 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 203 | if (rtc_istat & bits) { |
| 204 | rtc_istat_clear |= bits; | ||
| 202 | events |= RTC_AF | RTC_IRQF; | 205 | events |= RTC_AF | RTC_IRQF; |
| 203 | } | 206 | } |
| 204 | } | 207 | } |
| 205 | 208 | ||
| 206 | if (rtc_ictl & RTC_ISTAT_SEC) { | 209 | bits = RTC_ISTAT_SEC; |
| 207 | if (rtc_istat & RTC_ISTAT_SEC) { | 210 | if (rtc_ictl & bits) { |
| 208 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 211 | if (rtc_istat & bits) { |
| 212 | rtc_istat_clear |= bits; | ||
| 209 | events |= RTC_UF | RTC_IRQF; | 213 | events |= RTC_UF | RTC_IRQF; |
| 210 | } | 214 | } |
| 211 | } | 215 | } |
| @@ -213,9 +217,10 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | |||
| 213 | if (events) | 217 | if (events) |
| 214 | rtc_update_irq(rtc->rtc_dev, 1, events); | 218 | rtc_update_irq(rtc->rtc_dev, 1, events); |
| 215 | 219 | ||
| 216 | if (write_complete || events) | 220 | if (write_complete || events) { |
| 221 | bfin_write_RTC_ISTAT(rtc_istat_clear); | ||
| 217 | return IRQ_HANDLED; | 222 | return IRQ_HANDLED; |
| 218 | else | 223 | } else |
| 219 | return IRQ_NONE; | 224 | return IRQ_NONE; |
| 220 | } | 225 | } |
| 221 | 226 | ||
| @@ -422,9 +427,13 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev) | |||
| 422 | #ifdef CONFIG_PM | 427 | #ifdef CONFIG_PM |
| 423 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 428 | static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
| 424 | { | 429 | { |
| 425 | if (device_may_wakeup(&pdev->dev)) { | 430 | struct device *dev = &pdev->dev; |
| 431 | |||
| 432 | dev_dbg_stamp(dev); | ||
| 433 | |||
| 434 | if (device_may_wakeup(dev)) { | ||
| 426 | enable_irq_wake(IRQ_RTC); | 435 | enable_irq_wake(IRQ_RTC); |
| 427 | bfin_rtc_sync_pending(&pdev->dev); | 436 | bfin_rtc_sync_pending(dev); |
| 428 | } else | 437 | } else |
| 429 | bfin_rtc_int_clear(0); | 438 | bfin_rtc_int_clear(0); |
| 430 | 439 | ||
| @@ -433,7 +442,11 @@ static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 433 | 442 | ||
| 434 | static int bfin_rtc_resume(struct platform_device *pdev) | 443 | static int bfin_rtc_resume(struct platform_device *pdev) |
| 435 | { | 444 | { |
| 436 | if (device_may_wakeup(&pdev->dev)) | 445 | struct device *dev = &pdev->dev; |
| 446 | |||
| 447 | dev_dbg_stamp(dev); | ||
| 448 | |||
| 449 | if (device_may_wakeup(dev)) | ||
| 437 | disable_irq_wake(IRQ_RTC); | 450 | disable_irq_wake(IRQ_RTC); |
| 438 | 451 | ||
| 439 | /* | 452 | /* |
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 9de8516e3531..57063552d3b7 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C | 2 | * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2009-2010 Freescale Semiconductor. | 4 | * Copyright (C) 2009-2010 Freescale Semiconductor. |
| 5 | * Author: Jack Lan <jack.lan@freescale.com> | ||
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
| @@ -175,6 +176,182 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time) | |||
| 175 | DS3232_REG_SECONDS, 7, buf); | 176 | DS3232_REG_SECONDS, 7, buf); |
| 176 | } | 177 | } |
| 177 | 178 | ||
| 179 | /* | ||
| 180 | * DS3232 has two alarm, we only use alarm1 | ||
| 181 | * According to linux specification, only support one-shot alarm | ||
| 182 | * no periodic alarm mode | ||
| 183 | */ | ||
| 184 | static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 185 | { | ||
| 186 | struct i2c_client *client = to_i2c_client(dev); | ||
| 187 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
| 188 | int control, stat; | ||
| 189 | int ret; | ||
| 190 | u8 buf[4]; | ||
| 191 | |||
| 192 | mutex_lock(&ds3232->mutex); | ||
| 193 | |||
| 194 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
| 195 | if (ret < 0) | ||
| 196 | goto out; | ||
| 197 | stat = ret; | ||
| 198 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
| 199 | if (ret < 0) | ||
| 200 | goto out; | ||
| 201 | control = ret; | ||
| 202 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
| 203 | if (ret < 0) | ||
| 204 | goto out; | ||
| 205 | |||
| 206 | alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F); | ||
| 207 | alarm->time.tm_min = bcd2bin(buf[1] & 0x7F); | ||
| 208 | alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F); | ||
| 209 | alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F); | ||
| 210 | |||
| 211 | alarm->time.tm_mon = -1; | ||
| 212 | alarm->time.tm_year = -1; | ||
| 213 | alarm->time.tm_wday = -1; | ||
| 214 | alarm->time.tm_yday = -1; | ||
| 215 | alarm->time.tm_isdst = -1; | ||
| 216 | |||
| 217 | alarm->enabled = !!(control & DS3232_REG_CR_A1IE); | ||
| 218 | alarm->pending = !!(stat & DS3232_REG_SR_A1F); | ||
| 219 | |||
| 220 | ret = 0; | ||
| 221 | out: | ||
| 222 | mutex_unlock(&ds3232->mutex); | ||
| 223 | return ret; | ||
| 224 | } | ||
| 225 | |||
| 226 | /* | ||
| 227 | * linux rtc-module does not support wday alarm | ||
| 228 | * and only 24h time mode supported indeed | ||
| 229 | */ | ||
| 230 | static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
| 231 | { | ||
| 232 | struct i2c_client *client = to_i2c_client(dev); | ||
| 233 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
| 234 | int control, stat; | ||
| 235 | int ret; | ||
| 236 | u8 buf[4]; | ||
| 237 | |||
| 238 | if (client->irq <= 0) | ||
| 239 | return -EINVAL; | ||
| 240 | |||
| 241 | mutex_lock(&ds3232->mutex); | ||
| 242 | |||
| 243 | buf[0] = bin2bcd(alarm->time.tm_sec); | ||
| 244 | buf[1] = bin2bcd(alarm->time.tm_min); | ||
| 245 | buf[2] = bin2bcd(alarm->time.tm_hour); | ||
| 246 | buf[3] = bin2bcd(alarm->time.tm_mday); | ||
| 247 | |||
| 248 | /* clear alarm interrupt enable bit */ | ||
| 249 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
| 250 | if (ret < 0) | ||
| 251 | goto out; | ||
| 252 | control = ret; | ||
| 253 | control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); | ||
| 254 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
| 255 | if (ret < 0) | ||
| 256 | goto out; | ||
| 257 | |||
| 258 | /* clear any pending alarm flag */ | ||
| 259 | ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); | ||
| 260 | if (ret < 0) | ||
| 261 | goto out; | ||
| 262 | stat = ret; | ||
| 263 | stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); | ||
| 264 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); | ||
| 265 | if (ret < 0) | ||
| 266 | goto out; | ||
| 267 | |||
| 268 | ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
| 269 | |||
| 270 | if (alarm->enabled) { | ||
| 271 | control |= DS3232_REG_CR_A1IE; | ||
| 272 | ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
| 273 | } | ||
| 274 | out: | ||
| 275 | mutex_unlock(&ds3232->mutex); | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | |||
| 279 | static void ds3232_update_alarm(struct i2c_client *client) | ||
| 280 | { | ||
| 281 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
| 282 | int control; | ||
| 283 | int ret; | ||
| 284 | u8 buf[4]; | ||
| 285 | |||
| 286 | mutex_lock(&ds3232->mutex); | ||
| 287 | |||
| 288 | ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
| 289 | if (ret < 0) | ||
| 290 | goto unlock; | ||
| 291 | |||
| 292 | buf[0] = bcd2bin(buf[0]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
| 293 | 0x80 : buf[0]; | ||
| 294 | buf[1] = bcd2bin(buf[1]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
| 295 | 0x80 : buf[1]; | ||
| 296 | buf[2] = bcd2bin(buf[2]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
| 297 | 0x80 : buf[2]; | ||
| 298 | buf[3] = bcd2bin(buf[3]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ? | ||
| 299 | 0x80 : buf[3]; | ||
| 300 | |||
| 301 | ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); | ||
| 302 | if (ret < 0) | ||
| 303 | goto unlock; | ||
| 304 | |||
| 305 | control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); | ||
| 306 | if (control < 0) | ||
| 307 | goto unlock; | ||
| 308 | |||
| 309 | if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF)) | ||
| 310 | /* enable alarm1 interrupt */ | ||
| 311 | control |= DS3232_REG_CR_A1IE; | ||
| 312 | else | ||
| 313 | /* disable alarm1 interrupt */ | ||
| 314 | control &= ~(DS3232_REG_CR_A1IE); | ||
| 315 | i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); | ||
| 316 | |||
| 317 | unlock: | ||
| 318 | mutex_unlock(&ds3232->mutex); | ||
| 319 | } | ||
| 320 | |||
| 321 | static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
| 322 | { | ||
| 323 | struct i2c_client *client = to_i2c_client(dev); | ||
| 324 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
| 325 | |||
| 326 | if (client->irq <= 0) | ||
| 327 | return -EINVAL; | ||
| 328 | |||
| 329 | if (enabled) | ||
| 330 | ds3232->rtc->irq_data |= RTC_AF; | ||
| 331 | else | ||
| 332 | ds3232->rtc->irq_data &= ~RTC_AF; | ||
| 333 | |||
| 334 | ds3232_update_alarm(client); | ||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static int ds3232_update_irq_enable(struct device *dev, unsigned int enabled) | ||
| 339 | { | ||
| 340 | struct i2c_client *client = to_i2c_client(dev); | ||
| 341 | struct ds3232 *ds3232 = i2c_get_clientdata(client); | ||
| 342 | |||
| 343 | if (client->irq <= 0) | ||
| 344 | return -EINVAL; | ||
| 345 | |||
| 346 | if (enabled) | ||
| 347 | ds3232->rtc->irq_data |= RTC_UF; | ||
| 348 | else | ||
| 349 | ds3232->rtc->irq_data &= ~RTC_UF; | ||
| 350 | |||
| 351 | ds3232_update_alarm(client); | ||
| 352 | return 0; | ||
| 353 | } | ||
| 354 | |||
| 178 | static irqreturn_t ds3232_irq(int irq, void *dev_id) | 355 | static irqreturn_t ds3232_irq(int irq, void *dev_id) |
| 179 | { | 356 | { |
| 180 | struct i2c_client *client = dev_id; | 357 | struct i2c_client *client = dev_id; |
| @@ -222,6 +399,10 @@ unlock: | |||
| 222 | static const struct rtc_class_ops ds3232_rtc_ops = { | 399 | static const struct rtc_class_ops ds3232_rtc_ops = { |
| 223 | .read_time = ds3232_read_time, | 400 | .read_time = ds3232_read_time, |
| 224 | .set_time = ds3232_set_time, | 401 | .set_time = ds3232_set_time, |
| 402 | .read_alarm = ds3232_read_alarm, | ||
| 403 | .set_alarm = ds3232_set_alarm, | ||
| 404 | .alarm_irq_enable = ds3232_alarm_irq_enable, | ||
| 405 | .update_irq_enable = ds3232_update_irq_enable, | ||
| 225 | }; | 406 | }; |
| 226 | 407 | ||
| 227 | static int __devinit ds3232_probe(struct i2c_client *client, | 408 | static int __devinit ds3232_probe(struct i2c_client *client, |
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 2619d57b91d7..2e16f72c9056 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | 2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> |
| 3 | * Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net> | ||
| 3 | * JZ4740 SoC RTC driver | 4 | * JZ4740 SoC RTC driver |
| 4 | * | 5 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| @@ -161,7 +162,8 @@ static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 161 | 162 | ||
| 162 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); | 163 | ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC_ALARM, secs); |
| 163 | if (!ret) | 164 | if (!ret) |
| 164 | ret = jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AE, alrm->enabled); | 165 | ret = jz4740_rtc_ctrl_set_bits(rtc, |
| 166 | JZ_RTC_CTRL_AE | JZ_RTC_CTRL_AF_IRQ, alrm->enabled); | ||
| 165 | 167 | ||
| 166 | return ret; | 168 | return ret; |
| 167 | } | 169 | } |
| @@ -258,6 +260,8 @@ static int __devinit jz4740_rtc_probe(struct platform_device *pdev) | |||
| 258 | 260 | ||
| 259 | platform_set_drvdata(pdev, rtc); | 261 | platform_set_drvdata(pdev, rtc); |
| 260 | 262 | ||
| 263 | device_init_wakeup(&pdev->dev, 1); | ||
| 264 | |||
| 261 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, | 265 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &jz4740_rtc_ops, |
| 262 | THIS_MODULE); | 266 | THIS_MODULE); |
| 263 | if (IS_ERR(rtc->rtc)) { | 267 | if (IS_ERR(rtc->rtc)) { |
| @@ -318,12 +322,43 @@ static int __devexit jz4740_rtc_remove(struct platform_device *pdev) | |||
| 318 | return 0; | 322 | return 0; |
| 319 | } | 323 | } |
| 320 | 324 | ||
| 325 | |||
| 326 | #ifdef CONFIG_PM | ||
| 327 | static int jz4740_rtc_suspend(struct device *dev) | ||
| 328 | { | ||
| 329 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
| 330 | |||
| 331 | if (device_may_wakeup(dev)) | ||
| 332 | enable_irq_wake(rtc->irq); | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | static int jz4740_rtc_resume(struct device *dev) | ||
| 337 | { | ||
| 338 | struct jz4740_rtc *rtc = dev_get_drvdata(dev); | ||
| 339 | |||
| 340 | if (device_may_wakeup(dev)) | ||
| 341 | disable_irq_wake(rtc->irq); | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | static const struct dev_pm_ops jz4740_pm_ops = { | ||
| 346 | .suspend = jz4740_rtc_suspend, | ||
| 347 | .resume = jz4740_rtc_resume, | ||
| 348 | }; | ||
| 349 | #define JZ4740_RTC_PM_OPS (&jz4740_pm_ops) | ||
| 350 | |||
| 351 | #else | ||
| 352 | #define JZ4740_RTC_PM_OPS NULL | ||
| 353 | #endif /* CONFIG_PM */ | ||
| 354 | |||
| 321 | struct platform_driver jz4740_rtc_driver = { | 355 | struct platform_driver jz4740_rtc_driver = { |
| 322 | .probe = jz4740_rtc_probe, | 356 | .probe = jz4740_rtc_probe, |
| 323 | .remove = __devexit_p(jz4740_rtc_remove), | 357 | .remove = __devexit_p(jz4740_rtc_remove), |
| 324 | .driver = { | 358 | .driver = { |
| 325 | .name = "jz4740-rtc", | 359 | .name = "jz4740-rtc", |
| 326 | .owner = THIS_MODULE, | 360 | .owner = THIS_MODULE, |
| 361 | .pm = JZ4740_RTC_PM_OPS, | ||
| 327 | }, | 362 | }, |
| 328 | }; | 363 | }; |
| 329 | 364 | ||
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c new file mode 100644 index 000000000000..ec8701ce99f9 --- /dev/null +++ b/drivers/rtc/rtc-lpc32xx.c | |||
| @@ -0,0 +1,414 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010 NXP Semiconductors | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * You should have received a copy of the GNU General Public License along | ||
| 10 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 11 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/spinlock.h> | ||
| 19 | #include <linux/rtc.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | |||
| 23 | /* | ||
| 24 | * Clock and Power control register offsets | ||
| 25 | */ | ||
| 26 | #define LPC32XX_RTC_UCOUNT 0x00 | ||
| 27 | #define LPC32XX_RTC_DCOUNT 0x04 | ||
| 28 | #define LPC32XX_RTC_MATCH0 0x08 | ||
| 29 | #define LPC32XX_RTC_MATCH1 0x0C | ||
| 30 | #define LPC32XX_RTC_CTRL 0x10 | ||
| 31 | #define LPC32XX_RTC_INTSTAT 0x14 | ||
| 32 | #define LPC32XX_RTC_KEY 0x18 | ||
| 33 | #define LPC32XX_RTC_SRAM 0x80 | ||
| 34 | |||
| 35 | #define LPC32XX_RTC_CTRL_MATCH0 (1 << 0) | ||
| 36 | #define LPC32XX_RTC_CTRL_MATCH1 (1 << 1) | ||
| 37 | #define LPC32XX_RTC_CTRL_ONSW_MATCH0 (1 << 2) | ||
| 38 | #define LPC32XX_RTC_CTRL_ONSW_MATCH1 (1 << 3) | ||
| 39 | #define LPC32XX_RTC_CTRL_SW_RESET (1 << 4) | ||
| 40 | #define LPC32XX_RTC_CTRL_CNTR_DIS (1 << 6) | ||
| 41 | #define LPC32XX_RTC_CTRL_ONSW_FORCE_HI (1 << 7) | ||
| 42 | |||
| 43 | #define LPC32XX_RTC_INTSTAT_MATCH0 (1 << 0) | ||
| 44 | #define LPC32XX_RTC_INTSTAT_MATCH1 (1 << 1) | ||
| 45 | #define LPC32XX_RTC_INTSTAT_ONSW (1 << 2) | ||
| 46 | |||
| 47 | #define LPC32XX_RTC_KEY_ONSW_LOADVAL 0xB5C13F27 | ||
| 48 | |||
| 49 | #define RTC_NAME "rtc-lpc32xx" | ||
| 50 | |||
| 51 | #define rtc_readl(dev, reg) \ | ||
| 52 | __raw_readl((dev)->rtc_base + (reg)) | ||
| 53 | #define rtc_writel(dev, reg, val) \ | ||
| 54 | __raw_writel((val), (dev)->rtc_base + (reg)) | ||
| 55 | |||
| 56 | struct lpc32xx_rtc { | ||
| 57 | void __iomem *rtc_base; | ||
| 58 | int irq; | ||
| 59 | unsigned char alarm_enabled; | ||
| 60 | struct rtc_device *rtc; | ||
| 61 | spinlock_t lock; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time) | ||
| 65 | { | ||
| 66 | unsigned long elapsed_sec; | ||
| 67 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
| 68 | |||
| 69 | elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); | ||
| 70 | rtc_time_to_tm(elapsed_sec, time); | ||
| 71 | |||
| 72 | return rtc_valid_tm(time); | ||
| 73 | } | ||
| 74 | |||
| 75 | static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
| 76 | { | ||
| 77 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
| 78 | u32 tmp; | ||
| 79 | |||
| 80 | spin_lock_irq(&rtc->lock); | ||
| 81 | |||
| 82 | /* RTC must be disabled during count update */ | ||
| 83 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
| 84 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS); | ||
| 85 | rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs); | ||
| 86 | rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs); | ||
| 87 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS); | ||
| 88 | |||
| 89 | spin_unlock_irq(&rtc->lock); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int lpc32xx_rtc_read_alarm(struct device *dev, | ||
| 95 | struct rtc_wkalrm *wkalrm) | ||
| 96 | { | ||
| 97 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
| 98 | |||
| 99 | rtc_time_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time); | ||
| 100 | wkalrm->enabled = rtc->alarm_enabled; | ||
| 101 | wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) & | ||
| 102 | LPC32XX_RTC_INTSTAT_MATCH0); | ||
| 103 | |||
| 104 | return rtc_valid_tm(&wkalrm->time); | ||
| 105 | } | ||
| 106 | |||
| 107 | static int lpc32xx_rtc_set_alarm(struct device *dev, | ||
| 108 | struct rtc_wkalrm *wkalrm) | ||
| 109 | { | ||
| 110 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
| 111 | unsigned long alarmsecs; | ||
| 112 | u32 tmp; | ||
| 113 | int ret; | ||
| 114 | |||
| 115 | ret = rtc_tm_to_time(&wkalrm->time, &alarmsecs); | ||
| 116 | if (ret < 0) { | ||
| 117 | dev_warn(dev, "Failed to convert time: %d\n", ret); | ||
| 118 | return ret; | ||
| 119 | } | ||
| 120 | |||
| 121 | spin_lock_irq(&rtc->lock); | ||
| 122 | |||
| 123 | /* Disable alarm during update */ | ||
| 124 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
| 125 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0); | ||
| 126 | |||
| 127 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs); | ||
| 128 | |||
| 129 | rtc->alarm_enabled = wkalrm->enabled; | ||
| 130 | if (wkalrm->enabled) { | ||
| 131 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, | ||
| 132 | LPC32XX_RTC_INTSTAT_MATCH0); | ||
| 133 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | | ||
| 134 | LPC32XX_RTC_CTRL_MATCH0); | ||
| 135 | } | ||
| 136 | |||
| 137 | spin_unlock_irq(&rtc->lock); | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | static int lpc32xx_rtc_alarm_irq_enable(struct device *dev, | ||
| 143 | unsigned int enabled) | ||
| 144 | { | ||
| 145 | struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); | ||
| 146 | u32 tmp; | ||
| 147 | |||
| 148 | spin_lock_irq(&rtc->lock); | ||
| 149 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
| 150 | |||
| 151 | if (enabled) { | ||
| 152 | rtc->alarm_enabled = 1; | ||
| 153 | tmp |= LPC32XX_RTC_CTRL_MATCH0; | ||
| 154 | } else { | ||
| 155 | rtc->alarm_enabled = 0; | ||
| 156 | tmp &= ~LPC32XX_RTC_CTRL_MATCH0; | ||
| 157 | } | ||
| 158 | |||
| 159 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); | ||
| 160 | spin_unlock_irq(&rtc->lock); | ||
| 161 | |||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev) | ||
| 166 | { | ||
| 167 | struct lpc32xx_rtc *rtc = dev; | ||
| 168 | |||
| 169 | spin_lock(&rtc->lock); | ||
| 170 | |||
| 171 | /* Disable alarm interrupt */ | ||
| 172 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
| 173 | rtc_readl(rtc, LPC32XX_RTC_CTRL) & | ||
| 174 | ~LPC32XX_RTC_CTRL_MATCH0); | ||
| 175 | rtc->alarm_enabled = 0; | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Write a large value to the match value so the RTC won't | ||
| 179 | * keep firing the match status | ||
| 180 | */ | ||
| 181 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); | ||
| 182 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0); | ||
| 183 | |||
| 184 | spin_unlock(&rtc->lock); | ||
| 185 | |||
| 186 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 187 | |||
| 188 | return IRQ_HANDLED; | ||
| 189 | } | ||
| 190 | |||
| 191 | static const struct rtc_class_ops lpc32xx_rtc_ops = { | ||
| 192 | .read_time = lpc32xx_rtc_read_time, | ||
| 193 | .set_mmss = lpc32xx_rtc_set_mmss, | ||
| 194 | .read_alarm = lpc32xx_rtc_read_alarm, | ||
| 195 | .set_alarm = lpc32xx_rtc_set_alarm, | ||
| 196 | .alarm_irq_enable = lpc32xx_rtc_alarm_irq_enable, | ||
| 197 | }; | ||
| 198 | |||
| 199 | static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) | ||
| 200 | { | ||
| 201 | struct resource *res; | ||
| 202 | struct lpc32xx_rtc *rtc; | ||
| 203 | resource_size_t size; | ||
| 204 | int rtcirq; | ||
| 205 | u32 tmp; | ||
| 206 | |||
| 207 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 208 | if (!res) { | ||
| 209 | dev_err(&pdev->dev, "Can't get memory resource\n"); | ||
| 210 | return -ENOENT; | ||
| 211 | } | ||
| 212 | |||
| 213 | rtcirq = platform_get_irq(pdev, 0); | ||
| 214 | if (rtcirq < 0 || rtcirq >= NR_IRQS) { | ||
| 215 | dev_warn(&pdev->dev, "Can't get interrupt resource\n"); | ||
| 216 | rtcirq = -1; | ||
| 217 | } | ||
| 218 | |||
| 219 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
| 220 | if (unlikely(!rtc)) { | ||
| 221 | dev_err(&pdev->dev, "Can't allocate memory\n"); | ||
| 222 | return -ENOMEM; | ||
| 223 | } | ||
| 224 | rtc->irq = rtcirq; | ||
| 225 | |||
| 226 | size = resource_size(res); | ||
| 227 | |||
| 228 | if (!devm_request_mem_region(&pdev->dev, res->start, size, | ||
| 229 | pdev->name)) { | ||
| 230 | dev_err(&pdev->dev, "RTC registers are not free\n"); | ||
| 231 | return -EBUSY; | ||
| 232 | } | ||
| 233 | |||
| 234 | rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size); | ||
| 235 | if (!rtc->rtc_base) { | ||
| 236 | dev_err(&pdev->dev, "Can't map memory\n"); | ||
| 237 | return -ENOMEM; | ||
| 238 | } | ||
| 239 | |||
| 240 | spin_lock_init(&rtc->lock); | ||
| 241 | |||
| 242 | /* | ||
| 243 | * The RTC is on a seperate power domain and can keep it's state | ||
| 244 | * across a chip power cycle. If the RTC has never been previously | ||
| 245 | * setup, then set it up now for the first time. | ||
| 246 | */ | ||
| 247 | tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); | ||
| 248 | if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) { | ||
| 249 | tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET | | ||
| 250 | LPC32XX_RTC_CTRL_CNTR_DIS | | ||
| 251 | LPC32XX_RTC_CTRL_MATCH0 | | ||
| 252 | LPC32XX_RTC_CTRL_MATCH1 | | ||
| 253 | LPC32XX_RTC_CTRL_ONSW_MATCH0 | | ||
| 254 | LPC32XX_RTC_CTRL_ONSW_MATCH1 | | ||
| 255 | LPC32XX_RTC_CTRL_ONSW_FORCE_HI); | ||
| 256 | rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); | ||
| 257 | |||
| 258 | /* Clear latched interrupt states */ | ||
| 259 | rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); | ||
| 260 | rtc_writel(rtc, LPC32XX_RTC_INTSTAT, | ||
| 261 | LPC32XX_RTC_INTSTAT_MATCH0 | | ||
| 262 | LPC32XX_RTC_INTSTAT_MATCH1 | | ||
| 263 | LPC32XX_RTC_INTSTAT_ONSW); | ||
| 264 | |||
| 265 | /* Write key value to RTC so it won't reload on reset */ | ||
| 266 | rtc_writel(rtc, LPC32XX_RTC_KEY, | ||
| 267 | LPC32XX_RTC_KEY_ONSW_LOADVAL); | ||
| 268 | } else { | ||
| 269 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
| 270 | tmp & ~LPC32XX_RTC_CTRL_MATCH0); | ||
| 271 | } | ||
| 272 | |||
| 273 | platform_set_drvdata(pdev, rtc); | ||
| 274 | |||
| 275 | rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops, | ||
| 276 | THIS_MODULE); | ||
| 277 | if (IS_ERR(rtc->rtc)) { | ||
| 278 | dev_err(&pdev->dev, "Can't get RTC\n"); | ||
| 279 | platform_set_drvdata(pdev, NULL); | ||
| 280 | return PTR_ERR(rtc->rtc); | ||
| 281 | } | ||
| 282 | |||
| 283 | /* | ||
| 284 | * IRQ is enabled after device registration in case alarm IRQ | ||
| 285 | * is pending upon suspend exit. | ||
| 286 | */ | ||
| 287 | if (rtc->irq >= 0) { | ||
| 288 | if (devm_request_irq(&pdev->dev, rtc->irq, | ||
| 289 | lpc32xx_rtc_alarm_interrupt, | ||
| 290 | IRQF_DISABLED, pdev->name, rtc) < 0) { | ||
| 291 | dev_warn(&pdev->dev, "Can't request interrupt.\n"); | ||
| 292 | rtc->irq = -1; | ||
| 293 | } else { | ||
| 294 | device_init_wakeup(&pdev->dev, 1); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int __devexit lpc32xx_rtc_remove(struct platform_device *pdev) | ||
| 302 | { | ||
| 303 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
| 304 | |||
| 305 | if (rtc->irq >= 0) | ||
| 306 | device_init_wakeup(&pdev->dev, 0); | ||
| 307 | |||
| 308 | platform_set_drvdata(pdev, NULL); | ||
| 309 | rtc_device_unregister(rtc->rtc); | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | #ifdef CONFIG_PM | ||
| 315 | static int lpc32xx_rtc_suspend(struct device *dev) | ||
| 316 | { | ||
| 317 | struct platform_device *pdev = to_platform_device(dev); | ||
| 318 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
| 319 | |||
| 320 | if (rtc->irq >= 0) { | ||
| 321 | if (device_may_wakeup(&pdev->dev)) | ||
| 322 | enable_irq_wake(rtc->irq); | ||
| 323 | else | ||
| 324 | disable_irq_wake(rtc->irq); | ||
| 325 | } | ||
| 326 | |||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | static int lpc32xx_rtc_resume(struct device *dev) | ||
| 331 | { | ||
| 332 | struct platform_device *pdev = to_platform_device(dev); | ||
| 333 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
| 334 | |||
| 335 | if (rtc->irq >= 0 && device_may_wakeup(&pdev->dev)) | ||
| 336 | disable_irq_wake(rtc->irq); | ||
| 337 | |||
| 338 | return 0; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* Unconditionally disable the alarm */ | ||
| 342 | static int lpc32xx_rtc_freeze(struct device *dev) | ||
| 343 | { | ||
| 344 | struct platform_device *pdev = to_platform_device(dev); | ||
| 345 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
| 346 | |||
| 347 | spin_lock_irq(&rtc->lock); | ||
| 348 | |||
| 349 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
| 350 | rtc_readl(rtc, LPC32XX_RTC_CTRL) & | ||
| 351 | ~LPC32XX_RTC_CTRL_MATCH0); | ||
| 352 | |||
| 353 | spin_unlock_irq(&rtc->lock); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int lpc32xx_rtc_thaw(struct device *dev) | ||
| 359 | { | ||
| 360 | struct platform_device *pdev = to_platform_device(dev); | ||
| 361 | struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); | ||
| 362 | |||
| 363 | if (rtc->alarm_enabled) { | ||
| 364 | spin_lock_irq(&rtc->lock); | ||
| 365 | |||
| 366 | rtc_writel(rtc, LPC32XX_RTC_CTRL, | ||
| 367 | rtc_readl(rtc, LPC32XX_RTC_CTRL) | | ||
| 368 | LPC32XX_RTC_CTRL_MATCH0); | ||
| 369 | |||
| 370 | spin_unlock_irq(&rtc->lock); | ||
| 371 | } | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static const struct dev_pm_ops lpc32xx_rtc_pm_ops = { | ||
| 377 | .suspend = lpc32xx_rtc_suspend, | ||
| 378 | .resume = lpc32xx_rtc_resume, | ||
| 379 | .freeze = lpc32xx_rtc_freeze, | ||
| 380 | .thaw = lpc32xx_rtc_thaw, | ||
| 381 | .restore = lpc32xx_rtc_resume | ||
| 382 | }; | ||
| 383 | |||
| 384 | #define LPC32XX_RTC_PM_OPS (&lpc32xx_rtc_pm_ops) | ||
| 385 | #else | ||
| 386 | #define LPC32XX_RTC_PM_OPS NULL | ||
| 387 | #endif | ||
| 388 | |||
| 389 | static struct platform_driver lpc32xx_rtc_driver = { | ||
| 390 | .probe = lpc32xx_rtc_probe, | ||
| 391 | .remove = __devexit_p(lpc32xx_rtc_remove), | ||
| 392 | .driver = { | ||
| 393 | .name = RTC_NAME, | ||
| 394 | .owner = THIS_MODULE, | ||
| 395 | .pm = LPC32XX_RTC_PM_OPS | ||
| 396 | }, | ||
| 397 | }; | ||
| 398 | |||
| 399 | static int __init lpc32xx_rtc_init(void) | ||
| 400 | { | ||
| 401 | return platform_driver_register(&lpc32xx_rtc_driver); | ||
| 402 | } | ||
| 403 | module_init(lpc32xx_rtc_init); | ||
| 404 | |||
| 405 | static void __exit lpc32xx_rtc_exit(void) | ||
| 406 | { | ||
| 407 | platform_driver_unregister(&lpc32xx_rtc_driver); | ||
| 408 | } | ||
| 409 | module_exit(lpc32xx_rtc_exit); | ||
| 410 | |||
| 411 | MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); | ||
| 412 | MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); | ||
| 413 | MODULE_LICENSE("GPL"); | ||
| 414 | MODULE_ALIAS("platform:rtc-lpc32xx"); | ||
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 64d9727b7229..73377b0d65da 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
| @@ -34,7 +34,8 @@ | |||
| 34 | * Board-specific wiring options include using split power mode with | 34 | * Board-specific wiring options include using split power mode with |
| 35 | * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), | 35 | * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), |
| 36 | * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from | 36 | * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from |
| 37 | * low power modes). See the BOARD-SPECIFIC CUSTOMIZATION comment. | 37 | * low power modes) for OMAP1 boards (OMAP-L138 has this built into |
| 38 | * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. | ||
| 38 | */ | 39 | */ |
| 39 | 40 | ||
| 40 | #define OMAP_RTC_BASE 0xfffb4800 | 41 | #define OMAP_RTC_BASE 0xfffb4800 |
| @@ -401,16 +402,17 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
| 401 | 402 | ||
| 402 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: | 403 | /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: |
| 403 | * | 404 | * |
| 404 | * - Boards wired so that RTC_WAKE_INT does something, and muxed | 405 | * - Device wake-up capability setting should come through chip |
| 405 | * right (W13_1610_RTC_WAKE_INT is the default after chip reset), | 406 | * init logic. OMAP1 boards should initialize the "wakeup capable" |
| 406 | * should initialize the device wakeup flag appropriately. | 407 | * flag in the platform device if the board is wired right for |
| 408 | * being woken up by RTC alarm. For OMAP-L138, this capability | ||
| 409 | * is built into the SoC by the "Deep Sleep" capability. | ||
| 407 | * | 410 | * |
| 408 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, | 411 | * - Boards wired so RTC_ON_nOFF is used as the reset signal, |
| 409 | * rather than nPWRON_RESET, should forcibly enable split | 412 | * rather than nPWRON_RESET, should forcibly enable split |
| 410 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT | 413 | * power mode. (Some chip errata report that RTC_CTRL_SPLIT |
| 411 | * is write-only, and always reads as zero...) | 414 | * is write-only, and always reads as zero...) |
| 412 | */ | 415 | */ |
| 413 | device_init_wakeup(&pdev->dev, 0); | ||
| 414 | 416 | ||
| 415 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) | 417 | if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) |
| 416 | pr_info("%s: split power mode\n", pdev->name); | 418 | pr_info("%s: split power mode\n", pdev->name); |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index f57a87f4ae96..cf953ecbfca9 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
| @@ -100,7 +100,7 @@ static int s3c_rtc_setpie(struct device *dev, int enabled) | |||
| 100 | spin_lock_irq(&s3c_rtc_pie_lock); | 100 | spin_lock_irq(&s3c_rtc_pie_lock); |
| 101 | 101 | ||
| 102 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 102 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
| 103 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | 103 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
| 104 | tmp &= ~S3C64XX_RTCCON_TICEN; | 104 | tmp &= ~S3C64XX_RTCCON_TICEN; |
| 105 | 105 | ||
| 106 | if (enabled) | 106 | if (enabled) |
| @@ -171,8 +171,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
| 171 | goto retry_get_time; | 171 | goto retry_get_time; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", | 174 | pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n", |
| 175 | rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, | 175 | 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, |
| 176 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); | 176 | rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); |
| 177 | 177 | ||
| 178 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); | 178 | rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); |
| @@ -185,7 +185,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
| 185 | rtc_tm->tm_year += 100; | 185 | rtc_tm->tm_year += 100; |
| 186 | rtc_tm->tm_mon -= 1; | 186 | rtc_tm->tm_mon -= 1; |
| 187 | 187 | ||
| 188 | return 0; | 188 | return rtc_valid_tm(rtc_tm); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | 191 | static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) |
| @@ -193,8 +193,8 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
| 193 | void __iomem *base = s3c_rtc_base; | 193 | void __iomem *base = s3c_rtc_base; |
| 194 | int year = tm->tm_year - 100; | 194 | int year = tm->tm_year - 100; |
| 195 | 195 | ||
| 196 | pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", | 196 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", |
| 197 | tm->tm_year, tm->tm_mon, tm->tm_mday, | 197 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
| 198 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 198 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
| 199 | 199 | ||
| 200 | /* we get around y2k by simply not supporting it */ | 200 | /* we get around y2k by simply not supporting it */ |
| @@ -231,9 +231,9 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 231 | 231 | ||
| 232 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; | 232 | alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; |
| 233 | 233 | ||
| 234 | pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", | 234 | pr_debug("read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
| 235 | alm_en, | 235 | alm_en, |
| 236 | alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, | 236 | 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, |
| 237 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); | 237 | alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); |
| 238 | 238 | ||
| 239 | 239 | ||
| @@ -242,34 +242,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 242 | if (alm_en & S3C2410_RTCALM_SECEN) | 242 | if (alm_en & S3C2410_RTCALM_SECEN) |
| 243 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); | 243 | alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); |
| 244 | else | 244 | else |
| 245 | alm_tm->tm_sec = 0xff; | 245 | alm_tm->tm_sec = -1; |
| 246 | 246 | ||
| 247 | if (alm_en & S3C2410_RTCALM_MINEN) | 247 | if (alm_en & S3C2410_RTCALM_MINEN) |
| 248 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); | 248 | alm_tm->tm_min = bcd2bin(alm_tm->tm_min); |
| 249 | else | 249 | else |
| 250 | alm_tm->tm_min = 0xff; | 250 | alm_tm->tm_min = -1; |
| 251 | 251 | ||
| 252 | if (alm_en & S3C2410_RTCALM_HOUREN) | 252 | if (alm_en & S3C2410_RTCALM_HOUREN) |
| 253 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); | 253 | alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); |
| 254 | else | 254 | else |
| 255 | alm_tm->tm_hour = 0xff; | 255 | alm_tm->tm_hour = -1; |
| 256 | 256 | ||
| 257 | if (alm_en & S3C2410_RTCALM_DAYEN) | 257 | if (alm_en & S3C2410_RTCALM_DAYEN) |
| 258 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); | 258 | alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); |
| 259 | else | 259 | else |
| 260 | alm_tm->tm_mday = 0xff; | 260 | alm_tm->tm_mday = -1; |
| 261 | 261 | ||
| 262 | if (alm_en & S3C2410_RTCALM_MONEN) { | 262 | if (alm_en & S3C2410_RTCALM_MONEN) { |
| 263 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); | 263 | alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon); |
| 264 | alm_tm->tm_mon -= 1; | 264 | alm_tm->tm_mon -= 1; |
| 265 | } else { | 265 | } else { |
| 266 | alm_tm->tm_mon = 0xff; | 266 | alm_tm->tm_mon = -1; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | if (alm_en & S3C2410_RTCALM_YEAREN) | 269 | if (alm_en & S3C2410_RTCALM_YEAREN) |
| 270 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); | 270 | alm_tm->tm_year = bcd2bin(alm_tm->tm_year); |
| 271 | else | 271 | else |
| 272 | alm_tm->tm_year = 0xffff; | 272 | alm_tm->tm_year = -1; |
| 273 | 273 | ||
| 274 | return 0; | 274 | return 0; |
| 275 | } | 275 | } |
| @@ -280,10 +280,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 280 | void __iomem *base = s3c_rtc_base; | 280 | void __iomem *base = s3c_rtc_base; |
| 281 | unsigned int alrm_en; | 281 | unsigned int alrm_en; |
| 282 | 282 | ||
| 283 | pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", | 283 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
| 284 | alrm->enabled, | 284 | alrm->enabled, |
| 285 | tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, | 285 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
| 286 | tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); | 286 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
| 287 | 287 | ||
| 288 | 288 | ||
| 289 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; | 289 | alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; |
| @@ -318,7 +318,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
| 318 | unsigned int ticnt; | 318 | unsigned int ticnt; |
| 319 | 319 | ||
| 320 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 320 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
| 321 | ticnt = readb(s3c_rtc_base + S3C2410_RTCCON); | 321 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); |
| 322 | ticnt &= S3C64XX_RTCCON_TICEN; | 322 | ticnt &= S3C64XX_RTCCON_TICEN; |
| 323 | } else { | 323 | } else { |
| 324 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); | 324 | ticnt = readb(s3c_rtc_base + S3C2410_TICNT); |
| @@ -379,7 +379,8 @@ static const struct rtc_class_ops s3c_rtcops = { | |||
| 379 | .set_alarm = s3c_rtc_setalarm, | 379 | .set_alarm = s3c_rtc_setalarm, |
| 380 | .irq_set_freq = s3c_rtc_setfreq, | 380 | .irq_set_freq = s3c_rtc_setfreq, |
| 381 | .irq_set_state = s3c_rtc_setpie, | 381 | .irq_set_state = s3c_rtc_setpie, |
| 382 | .proc = s3c_rtc_proc, | 382 | .proc = s3c_rtc_proc, |
| 383 | .alarm_irq_enable = s3c_rtc_setaie, | ||
| 383 | }; | 384 | }; |
| 384 | 385 | ||
| 385 | static void s3c_rtc_enable(struct platform_device *pdev, int en) | 386 | static void s3c_rtc_enable(struct platform_device *pdev, int en) |
| @@ -391,11 +392,11 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
| 391 | return; | 392 | return; |
| 392 | 393 | ||
| 393 | if (!en) { | 394 | if (!en) { |
| 394 | tmp = readb(base + S3C2410_RTCCON); | 395 | tmp = readw(base + S3C2410_RTCCON); |
| 395 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 396 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
| 396 | tmp &= ~S3C64XX_RTCCON_TICEN; | 397 | tmp &= ~S3C64XX_RTCCON_TICEN; |
| 397 | tmp &= ~S3C2410_RTCCON_RTCEN; | 398 | tmp &= ~S3C2410_RTCCON_RTCEN; |
| 398 | writeb(tmp, base + S3C2410_RTCCON); | 399 | writew(tmp, base + S3C2410_RTCCON); |
| 399 | 400 | ||
| 400 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | 401 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
| 401 | tmp = readb(base + S3C2410_TICNT); | 402 | tmp = readb(base + S3C2410_TICNT); |
| @@ -405,25 +406,28 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
| 405 | } else { | 406 | } else { |
| 406 | /* re-enable the device, and check it is ok */ | 407 | /* re-enable the device, and check it is ok */ |
| 407 | 408 | ||
| 408 | if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ | 409 | if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) { |
| 409 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); | 410 | dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); |
| 410 | 411 | ||
| 411 | tmp = readb(base + S3C2410_RTCCON); | 412 | tmp = readw(base + S3C2410_RTCCON); |
| 412 | writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); | 413 | writew(tmp | S3C2410_RTCCON_RTCEN, |
| 414 | base + S3C2410_RTCCON); | ||
| 413 | } | 415 | } |
| 414 | 416 | ||
| 415 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ | 417 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) { |
| 416 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); | 418 | dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); |
| 417 | 419 | ||
| 418 | tmp = readb(base + S3C2410_RTCCON); | 420 | tmp = readw(base + S3C2410_RTCCON); |
| 419 | writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); | 421 | writew(tmp & ~S3C2410_RTCCON_CNTSEL, |
| 422 | base + S3C2410_RTCCON); | ||
| 420 | } | 423 | } |
| 421 | 424 | ||
| 422 | if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ | 425 | if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) { |
| 423 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); | 426 | dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); |
| 424 | 427 | ||
| 425 | tmp = readb(base + S3C2410_RTCCON); | 428 | tmp = readw(base + S3C2410_RTCCON); |
| 426 | writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); | 429 | writew(tmp & ~S3C2410_RTCCON_CLKRST, |
| 430 | base + S3C2410_RTCCON); | ||
| 427 | } | 431 | } |
| 428 | } | 432 | } |
| 429 | } | 433 | } |
| @@ -452,8 +456,8 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
| 452 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) | 456 | static int __devinit s3c_rtc_probe(struct platform_device *pdev) |
| 453 | { | 457 | { |
| 454 | struct rtc_device *rtc; | 458 | struct rtc_device *rtc; |
| 459 | struct rtc_time rtc_tm; | ||
| 455 | struct resource *res; | 460 | struct resource *res; |
| 456 | unsigned int tmp, i; | ||
| 457 | int ret; | 461 | int ret; |
| 458 | 462 | ||
| 459 | pr_debug("%s: probe=%p\n", __func__, pdev); | 463 | pr_debug("%s: probe=%p\n", __func__, pdev); |
| @@ -514,8 +518,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
| 514 | 518 | ||
| 515 | s3c_rtc_enable(pdev, 1); | 519 | s3c_rtc_enable(pdev, 1); |
| 516 | 520 | ||
| 517 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", | 521 | pr_debug("s3c2410_rtc: RTCCON=%02x\n", |
| 518 | readb(s3c_rtc_base + S3C2410_RTCCON)); | 522 | readw(s3c_rtc_base + S3C2410_RTCCON)); |
| 519 | 523 | ||
| 520 | device_init_wakeup(&pdev->dev, 1); | 524 | device_init_wakeup(&pdev->dev, 1); |
| 521 | 525 | ||
| @@ -534,11 +538,19 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
| 534 | 538 | ||
| 535 | /* Check RTC Time */ | 539 | /* Check RTC Time */ |
| 536 | 540 | ||
| 537 | for (i = S3C2410_RTCSEC; i <= S3C2410_RTCYEAR; i += 0x4) { | 541 | s3c_rtc_gettime(NULL, &rtc_tm); |
| 538 | tmp = readb(s3c_rtc_base + i); | 542 | |
| 543 | if (rtc_valid_tm(&rtc_tm)) { | ||
| 544 | rtc_tm.tm_year = 100; | ||
| 545 | rtc_tm.tm_mon = 0; | ||
| 546 | rtc_tm.tm_mday = 1; | ||
| 547 | rtc_tm.tm_hour = 0; | ||
| 548 | rtc_tm.tm_min = 0; | ||
| 549 | rtc_tm.tm_sec = 0; | ||
| 550 | |||
| 551 | s3c_rtc_settime(NULL, &rtc_tm); | ||
| 539 | 552 | ||
| 540 | if ((tmp & 0xf) > 0x9 || ((tmp >> 4) & 0xf) > 0x9) | 553 | dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); |
| 541 | writeb(0, s3c_rtc_base + i); | ||
| 542 | } | 554 | } |
| 543 | 555 | ||
| 544 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 556 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
| @@ -578,7 +590,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 578 | /* save TICNT for anyone using periodic interrupts */ | 590 | /* save TICNT for anyone using periodic interrupts */ |
| 579 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 591 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
| 580 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 592 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
| 581 | ticnt_en_save = readb(s3c_rtc_base + S3C2410_RTCCON); | 593 | ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); |
| 582 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; | 594 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; |
| 583 | } | 595 | } |
| 584 | s3c_rtc_enable(pdev, 0); | 596 | s3c_rtc_enable(pdev, 0); |
| @@ -596,8 +608,8 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
| 596 | s3c_rtc_enable(pdev, 1); | 608 | s3c_rtc_enable(pdev, 1); |
| 597 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 609 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
| 598 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | 610 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { |
| 599 | tmp = readb(s3c_rtc_base + S3C2410_RTCCON); | 611 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
| 600 | writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); | 612 | writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); |
| 601 | } | 613 | } |
| 602 | 614 | ||
| 603 | if (device_may_wakeup(&pdev->dev)) | 615 | if (device_may_wakeup(&pdev->dev)) |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 42e303ff862a..0e6aa3d96a42 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -697,9 +697,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 697 | struct inode *inode = file->f_path.dentry->d_inode; | 697 | struct inode *inode = file->f_path.dentry->d_inode; |
| 698 | int fbidx = iminor(inode); | 698 | int fbidx = iminor(inode); |
| 699 | struct fb_info *info = registered_fb[fbidx]; | 699 | struct fb_info *info = registered_fb[fbidx]; |
| 700 | u32 *buffer, *dst; | 700 | u8 *buffer, *dst; |
| 701 | u32 __iomem *src; | 701 | u8 __iomem *src; |
| 702 | int c, i, cnt = 0, err = 0; | 702 | int c, cnt = 0, err = 0; |
| 703 | unsigned long total_size; | 703 | unsigned long total_size; |
| 704 | 704 | ||
| 705 | if (!info || ! info->screen_base) | 705 | if (!info || ! info->screen_base) |
| @@ -730,7 +730,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 730 | if (!buffer) | 730 | if (!buffer) |
| 731 | return -ENOMEM; | 731 | return -ENOMEM; |
| 732 | 732 | ||
| 733 | src = (u32 __iomem *) (info->screen_base + p); | 733 | src = (u8 __iomem *) (info->screen_base + p); |
| 734 | 734 | ||
| 735 | if (info->fbops->fb_sync) | 735 | if (info->fbops->fb_sync) |
| 736 | info->fbops->fb_sync(info); | 736 | info->fbops->fb_sync(info); |
| @@ -738,17 +738,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 738 | while (count) { | 738 | while (count) { |
| 739 | c = (count > PAGE_SIZE) ? PAGE_SIZE : count; | 739 | c = (count > PAGE_SIZE) ? PAGE_SIZE : count; |
| 740 | dst = buffer; | 740 | dst = buffer; |
| 741 | for (i = c >> 2; i--; ) | 741 | fb_memcpy_fromfb(dst, src, c); |
| 742 | *dst++ = fb_readl(src++); | 742 | dst += c; |
| 743 | if (c & 3) { | 743 | src += c; |
| 744 | u8 *dst8 = (u8 *) dst; | ||
| 745 | u8 __iomem *src8 = (u8 __iomem *) src; | ||
| 746 | |||
| 747 | for (i = c & 3; i--;) | ||
| 748 | *dst8++ = fb_readb(src8++); | ||
| 749 | |||
| 750 | src = (u32 __iomem *) src8; | ||
| 751 | } | ||
| 752 | 744 | ||
| 753 | if (copy_to_user(buf, buffer, c)) { | 745 | if (copy_to_user(buf, buffer, c)) { |
| 754 | err = -EFAULT; | 746 | err = -EFAULT; |
| @@ -772,9 +764,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
| 772 | struct inode *inode = file->f_path.dentry->d_inode; | 764 | struct inode *inode = file->f_path.dentry->d_inode; |
| 773 | int fbidx = iminor(inode); | 765 | int fbidx = iminor(inode); |
| 774 | struct fb_info *info = registered_fb[fbidx]; | 766 | struct fb_info *info = registered_fb[fbidx]; |
| 775 | u32 *buffer, *src; | 767 | u8 *buffer, *src; |
| 776 | u32 __iomem *dst; | 768 | u8 __iomem *dst; |
| 777 | int c, i, cnt = 0, err = 0; | 769 | int c, cnt = 0, err = 0; |
| 778 | unsigned long total_size; | 770 | unsigned long total_size; |
| 779 | 771 | ||
| 780 | if (!info || !info->screen_base) | 772 | if (!info || !info->screen_base) |
| @@ -811,7 +803,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
| 811 | if (!buffer) | 803 | if (!buffer) |
| 812 | return -ENOMEM; | 804 | return -ENOMEM; |
| 813 | 805 | ||
| 814 | dst = (u32 __iomem *) (info->screen_base + p); | 806 | dst = (u8 __iomem *) (info->screen_base + p); |
| 815 | 807 | ||
| 816 | if (info->fbops->fb_sync) | 808 | if (info->fbops->fb_sync) |
| 817 | info->fbops->fb_sync(info); | 809 | info->fbops->fb_sync(info); |
| @@ -825,19 +817,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
| 825 | break; | 817 | break; |
| 826 | } | 818 | } |
| 827 | 819 | ||
| 828 | for (i = c >> 2; i--; ) | 820 | fb_memcpy_tofb(dst, src, c); |
| 829 | fb_writel(*src++, dst++); | 821 | dst += c; |
| 830 | 822 | src += c; | |
| 831 | if (c & 3) { | ||
| 832 | u8 *src8 = (u8 *) src; | ||
| 833 | u8 __iomem *dst8 = (u8 __iomem *) dst; | ||
| 834 | |||
| 835 | for (i = c & 3; i--; ) | ||
| 836 | fb_writeb(*src8++, dst8++); | ||
| 837 | |||
| 838 | dst = (u32 __iomem *) dst8; | ||
| 839 | } | ||
| 840 | |||
| 841 | *ppos += c; | 823 | *ppos += c; |
| 842 | buf += c; | 824 | buf += c; |
| 843 | cnt += c; | 825 | cnt += c; |
| @@ -877,13 +859,13 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) | |||
| 877 | 859 | ||
| 878 | if ((err = info->fbops->fb_pan_display(var, info))) | 860 | if ((err = info->fbops->fb_pan_display(var, info))) |
| 879 | return err; | 861 | return err; |
| 880 | info->var.xoffset = var->xoffset; | 862 | info->var.xoffset = var->xoffset; |
| 881 | info->var.yoffset = var->yoffset; | 863 | info->var.yoffset = var->yoffset; |
| 882 | if (var->vmode & FB_VMODE_YWRAP) | 864 | if (var->vmode & FB_VMODE_YWRAP) |
| 883 | info->var.vmode |= FB_VMODE_YWRAP; | 865 | info->var.vmode |= FB_VMODE_YWRAP; |
| 884 | else | 866 | else |
| 885 | info->var.vmode &= ~FB_VMODE_YWRAP; | 867 | info->var.vmode &= ~FB_VMODE_YWRAP; |
| 886 | return 0; | 868 | return 0; |
| 887 | } | 869 | } |
| 888 | 870 | ||
| 889 | static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, | 871 | static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, |
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index ca3355e430bf..933899dca33a 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c | |||
| @@ -1143,8 +1143,10 @@ static int __devinit gbefb_probe(struct platform_device *p_dev) | |||
| 1143 | return -ENOMEM; | 1143 | return -ENOMEM; |
| 1144 | 1144 | ||
| 1145 | #ifndef MODULE | 1145 | #ifndef MODULE |
| 1146 | if (fb_get_options("gbefb", &options)) | 1146 | if (fb_get_options("gbefb", &options)) { |
| 1147 | return -ENODEV; | 1147 | ret = -ENODEV; |
| 1148 | goto out_release_framebuffer; | ||
| 1149 | } | ||
| 1148 | gbefb_setup(options); | 1150 | gbefb_setup(options); |
| 1149 | #endif | 1151 | #endif |
| 1150 | 1152 | ||
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index f9fa0fd00292..1717623aabc0 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c | |||
| @@ -869,12 +869,9 @@ static int MGAG100_preinit(struct matrox_fb_info *minfo) | |||
| 869 | minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100 | 869 | minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100 |
| 870 | ? minfo->devflags.sgram : 1; | 870 | ? minfo->devflags.sgram : 1; |
| 871 | 871 | ||
| 872 | #ifdef CONFIG_FB_MATROX_G | ||
| 873 | if (minfo->devflags.g450dac) { | 872 | if (minfo->devflags.g450dac) { |
| 874 | minfo->outputs[0].output = &g450out; | 873 | minfo->outputs[0].output = &g450out; |
| 875 | } else | 874 | } else { |
| 876 | #endif | ||
| 877 | { | ||
| 878 | minfo->outputs[0].output = &m1064; | 875 | minfo->outputs[0].output = &m1064; |
| 879 | } | 876 | } |
| 880 | minfo->outputs[0].src = minfo->outputs[0].default_src; | 877 | minfo->outputs[0].src = minfo->outputs[0].default_src; |
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 1e3e8f19783e..31b8f67477b7 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c | |||
| @@ -280,7 +280,7 @@ static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll, | |||
| 280 | return fxtal * (*feed) / (*in) * ctl->den; | 280 | return fxtal * (*feed) / (*in) * ctl->den; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static unsigned int matroxfb_mavenclock(const struct matrox_pll_ctl* ctl, | 283 | static int matroxfb_mavenclock(const struct matrox_pll_ctl *ctl, |
| 284 | unsigned int htotal, unsigned int vtotal, | 284 | unsigned int htotal, unsigned int vtotal, |
| 285 | unsigned int* in, unsigned int* feed, unsigned int* post, | 285 | unsigned int* in, unsigned int* feed, unsigned int* post, |
| 286 | unsigned int* htotal2) { | 286 | unsigned int* htotal2) { |
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c index 2ffb34af4c59..87785c215a52 100644 --- a/drivers/video/omap/blizzard.c +++ b/drivers/video/omap/blizzard.c | |||
| @@ -1590,7 +1590,7 @@ static int blizzard_init(struct omapfb_device *fbdev, int ext_mode, | |||
| 1590 | blizzard.auto_update_window.width = fbdev->panel->x_res; | 1590 | blizzard.auto_update_window.width = fbdev->panel->x_res; |
| 1591 | blizzard.auto_update_window.height = fbdev->panel->y_res; | 1591 | blizzard.auto_update_window.height = fbdev->panel->y_res; |
| 1592 | blizzard.auto_update_window.out_x = 0; | 1592 | blizzard.auto_update_window.out_x = 0; |
| 1593 | blizzard.auto_update_window.out_x = 0; | 1593 | blizzard.auto_update_window.out_y = 0; |
| 1594 | blizzard.auto_update_window.out_width = fbdev->panel->x_res; | 1594 | blizzard.auto_update_window.out_width = fbdev->panel->x_res; |
| 1595 | blizzard.auto_update_window.out_height = fbdev->panel->y_res; | 1595 | blizzard.auto_update_window.out_height = fbdev->panel->y_res; |
| 1596 | blizzard.auto_update_window.format = 0; | 1596 | blizzard.auto_update_window.format = 0; |
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index ed371c868b3a..b16e6138fdd4 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c | |||
| @@ -181,6 +181,15 @@ void savagefb_create_i2c_busses(struct fb_info *info) | |||
| 181 | par->chan.algo.getscl = prosavage_gpio_getscl; | 181 | par->chan.algo.getscl = prosavage_gpio_getscl; |
| 182 | break; | 182 | break; |
| 183 | case FB_ACCEL_SAVAGE4: | 183 | case FB_ACCEL_SAVAGE4: |
| 184 | par->chan.reg = CR_SERIAL1; | ||
| 185 | if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40)) | ||
| 186 | par->chan.reg = CR_SERIAL2; | ||
| 187 | par->chan.ioaddr = par->mmio.vbase; | ||
| 188 | par->chan.algo.setsda = prosavage_gpio_setsda; | ||
| 189 | par->chan.algo.setscl = prosavage_gpio_setscl; | ||
| 190 | par->chan.algo.getsda = prosavage_gpio_getsda; | ||
| 191 | par->chan.algo.getscl = prosavage_gpio_getscl; | ||
| 192 | break; | ||
| 184 | case FB_ACCEL_SAVAGE2000: | 193 | case FB_ACCEL_SAVAGE2000: |
| 185 | par->chan.reg = 0xff20; | 194 | par->chan.reg = 0xff20; |
| 186 | par->chan.ioaddr = par->mmio.vbase; | 195 | par->chan.ioaddr = par->mmio.vbase; |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 2839e281cd65..b7b5014ff714 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
| @@ -517,10 +517,10 @@ static W1_MASTER_ATTR_RO(max_slave_count, S_IRUGO); | |||
| 517 | static W1_MASTER_ATTR_RO(attempts, S_IRUGO); | 517 | static W1_MASTER_ATTR_RO(attempts, S_IRUGO); |
| 518 | static W1_MASTER_ATTR_RO(timeout, S_IRUGO); | 518 | static W1_MASTER_ATTR_RO(timeout, S_IRUGO); |
| 519 | static W1_MASTER_ATTR_RO(pointer, S_IRUGO); | 519 | static W1_MASTER_ATTR_RO(pointer, S_IRUGO); |
| 520 | static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO); | 520 | static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUSR | S_IWGRP); |
| 521 | static W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUGO); | 521 | static W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUSR | S_IWGRP); |
| 522 | static W1_MASTER_ATTR_RW(add, S_IRUGO | S_IWUGO); | 522 | static W1_MASTER_ATTR_RW(add, S_IRUGO | S_IWUSR | S_IWGRP); |
| 523 | static W1_MASTER_ATTR_RW(remove, S_IRUGO | S_IWUGO); | 523 | static W1_MASTER_ATTR_RW(remove, S_IRUGO | S_IWUSR | S_IWGRP); |
| 524 | 524 | ||
| 525 | static struct attribute *w1_master_default_attrs[] = { | 525 | static struct attribute *w1_master_default_attrs[] = { |
| 526 | &w1_master_attribute_name.attr, | 526 | &w1_master_attribute_name.attr, |
