diff options
Diffstat (limited to 'drivers')
43 files changed, 4322 insertions, 625 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index d236aef7e59f..63b81826cb55 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -140,4 +140,8 @@ source "drivers/virt/Kconfig" | |||
140 | 140 | ||
141 | source "drivers/devfreq/Kconfig" | 141 | source "drivers/devfreq/Kconfig" |
142 | 142 | ||
143 | source "drivers/extcon/Kconfig" | ||
144 | |||
145 | source "drivers/memory/Kconfig" | ||
146 | |||
143 | endmenu | 147 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index 95952c82bf16..265b506a15be 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -134,3 +134,5 @@ obj-$(CONFIG_VIRT_DRIVERS) += virt/ | |||
134 | obj-$(CONFIG_HYPERV) += hv/ | 134 | obj-$(CONFIG_HYPERV) += hv/ |
135 | 135 | ||
136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ | 136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ |
137 | obj-$(CONFIG_EXTCON) += extcon/ | ||
138 | obj-$(CONFIG_MEMORY) += memory/ | ||
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 4a29763b8eb4..a12808259dfb 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -720,21 +720,21 @@ static int acpi_pci_link_add(struct acpi_device *device) | |||
720 | acpi_device_bid(device)); | 720 | acpi_device_bid(device)); |
721 | for (i = 0; i < link->irq.possible_count; i++) { | 721 | for (i = 0; i < link->irq.possible_count; i++) { |
722 | if (link->irq.active == link->irq.possible[i]) { | 722 | if (link->irq.active == link->irq.possible[i]) { |
723 | printk(" *%d", link->irq.possible[i]); | 723 | printk(KERN_CONT " *%d", link->irq.possible[i]); |
724 | found = 1; | 724 | found = 1; |
725 | } else | 725 | } else |
726 | printk(" %d", link->irq.possible[i]); | 726 | printk(KERN_CONT " %d", link->irq.possible[i]); |
727 | } | 727 | } |
728 | 728 | ||
729 | printk(")"); | 729 | printk(KERN_CONT ")"); |
730 | 730 | ||
731 | if (!found) | 731 | if (!found) |
732 | printk(" *%d", link->irq.active); | 732 | printk(KERN_CONT " *%d", link->irq.active); |
733 | 733 | ||
734 | if (!link->device->status.enabled) | 734 | if (!link->device->status.enabled) |
735 | printk(", disabled."); | 735 | printk(KERN_CONT ", disabled."); |
736 | 736 | ||
737 | printk("\n"); | 737 | printk(KERN_CONT "\n"); |
738 | 738 | ||
739 | list_add_tail(&link->list, &acpi_link_list); | 739 | list_add_tail(&link->list, &acpi_link_list); |
740 | 740 | ||
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index eb6fd233764b..06527c526618 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -887,7 +887,7 @@ int __init acpi_sleep_init(void) | |||
887 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); | 887 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); |
888 | if (ACPI_SUCCESS(status)) { | 888 | if (ACPI_SUCCESS(status)) { |
889 | sleep_states[i] = 1; | 889 | sleep_states[i] = 1; |
890 | printk(" S%d", i); | 890 | printk(KERN_CONT " S%d", i); |
891 | } | 891 | } |
892 | } | 892 | } |
893 | 893 | ||
@@ -901,7 +901,7 @@ int __init acpi_sleep_init(void) | |||
901 | hibernation_set_ops(old_suspend_ordering ? | 901 | hibernation_set_ops(old_suspend_ordering ? |
902 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); | 902 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); |
903 | sleep_states[ACPI_STATE_S4] = 1; | 903 | sleep_states[ACPI_STATE_S4] = 1; |
904 | printk(" S4"); | 904 | printk(KERN_CONT " S4"); |
905 | if (!nosigcheck) { | 905 | if (!nosigcheck) { |
906 | acpi_get_table(ACPI_SIG_FACS, 1, | 906 | acpi_get_table(ACPI_SIG_FACS, 1, |
907 | (struct acpi_table_header **)&facs); | 907 | (struct acpi_table_header **)&facs); |
@@ -914,11 +914,11 @@ int __init acpi_sleep_init(void) | |||
914 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); | 914 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); |
915 | if (ACPI_SUCCESS(status)) { | 915 | if (ACPI_SUCCESS(status)) { |
916 | sleep_states[ACPI_STATE_S5] = 1; | 916 | sleep_states[ACPI_STATE_S5] = 1; |
917 | printk(" S5"); | 917 | printk(KERN_CONT " S5"); |
918 | pm_power_off_prepare = acpi_power_off_prepare; | 918 | pm_power_off_prepare = acpi_power_off_prepare; |
919 | pm_power_off = acpi_power_off; | 919 | pm_power_off = acpi_power_off; |
920 | } | 920 | } |
921 | printk(")\n"); | 921 | printk(KERN_CONT ")\n"); |
922 | /* | 922 | /* |
923 | * Register the tts_notifier to reboot notifier list so that the _TTS | 923 | * Register the tts_notifier to reboot notifier list so that the _TTS |
924 | * object can also be evaluated when the system enters S5. | 924 | * object can also be evaluated when the system enters S5. |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 26a06b801b5b..2bcef657a60c 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include "power/power.h" | 21 | #include "power/power.h" |
22 | 22 | ||
23 | /* /sys/devices/system */ | 23 | /* /sys/devices/system */ |
24 | /* FIXME: make static after drivers/base/sys.c is deleted */ | 24 | static struct kset *system_kset; |
25 | struct kset *system_kset; | ||
26 | 25 | ||
27 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) | 26 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) |
28 | 27 | ||
diff --git a/drivers/base/core.c b/drivers/base/core.c index e28ce9898af4..346be8b78b24 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/async.h> | 26 | #include <linux/async.h> |
27 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
28 | #include <linux/netdevice.h> | ||
28 | 29 | ||
29 | #include "base.h" | 30 | #include "base.h" |
30 | #include "power/power.h" | 31 | #include "power/power.h" |
@@ -65,7 +66,7 @@ static inline int device_is_not_partition(struct device *dev) | |||
65 | * @dev: struct device to get the name of | 66 | * @dev: struct device to get the name of |
66 | * | 67 | * |
67 | * Will return the device's driver's name if it is bound to a device. If | 68 | * Will return the device's driver's name if it is bound to a device. If |
68 | * the device is not bound to a device, it will return the name of the bus | 69 | * the device is not bound to a driver, it will return the name of the bus |
69 | * it is attached to. If it is not attached to a bus either, an empty | 70 | * it is attached to. If it is not attached to a bus either, an empty |
70 | * string will be returned. | 71 | * string will be returned. |
71 | */ | 72 | */ |
@@ -878,8 +879,8 @@ EXPORT_SYMBOL_GPL(dev_set_name); | |||
878 | * to NULL prevents an entry from being created. class->dev_kobj must | 879 | * to NULL prevents an entry from being created. class->dev_kobj must |
879 | * be set (or cleared) before any devices are registered to the class | 880 | * be set (or cleared) before any devices are registered to the class |
880 | * otherwise device_create_sys_dev_entry() and | 881 | * otherwise device_create_sys_dev_entry() and |
881 | * device_remove_sys_dev_entry() will disagree about the the presence | 882 | * device_remove_sys_dev_entry() will disagree about the presence of |
882 | * of the link. | 883 | * the link. |
883 | */ | 884 | */ |
884 | static struct kobject *device_to_dev_kobj(struct device *dev) | 885 | static struct kobject *device_to_dev_kobj(struct device *dev) |
885 | { | 886 | { |
@@ -1843,15 +1844,60 @@ void device_shutdown(void) | |||
1843 | */ | 1844 | */ |
1844 | 1845 | ||
1845 | #ifdef CONFIG_PRINTK | 1846 | #ifdef CONFIG_PRINTK |
1846 | |||
1847 | int __dev_printk(const char *level, const struct device *dev, | 1847 | int __dev_printk(const char *level, const struct device *dev, |
1848 | struct va_format *vaf) | 1848 | struct va_format *vaf) |
1849 | { | 1849 | { |
1850 | char dict[128]; | ||
1851 | size_t dictlen = 0; | ||
1852 | const char *subsys; | ||
1853 | |||
1850 | if (!dev) | 1854 | if (!dev) |
1851 | return printk("%s(NULL device *): %pV", level, vaf); | 1855 | return printk("%s(NULL device *): %pV", level, vaf); |
1852 | 1856 | ||
1853 | return printk("%s%s %s: %pV", | 1857 | if (dev->class) |
1854 | level, dev_driver_string(dev), dev_name(dev), vaf); | 1858 | subsys = dev->class->name; |
1859 | else if (dev->bus) | ||
1860 | subsys = dev->bus->name; | ||
1861 | else | ||
1862 | goto skip; | ||
1863 | |||
1864 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1865 | "SUBSYSTEM=%s", subsys); | ||
1866 | |||
1867 | /* | ||
1868 | * Add device identifier DEVICE=: | ||
1869 | * b12:8 block dev_t | ||
1870 | * c127:3 char dev_t | ||
1871 | * n8 netdev ifindex | ||
1872 | * +sound:card0 subsystem:devname | ||
1873 | */ | ||
1874 | if (MAJOR(dev->devt)) { | ||
1875 | char c; | ||
1876 | |||
1877 | if (strcmp(subsys, "block") == 0) | ||
1878 | c = 'b'; | ||
1879 | else | ||
1880 | c = 'c'; | ||
1881 | dictlen++; | ||
1882 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1883 | "DEVICE=%c%u:%u", | ||
1884 | c, MAJOR(dev->devt), MINOR(dev->devt)); | ||
1885 | } else if (strcmp(subsys, "net") == 0) { | ||
1886 | struct net_device *net = to_net_dev(dev); | ||
1887 | |||
1888 | dictlen++; | ||
1889 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1890 | "DEVICE=n%u", net->ifindex); | ||
1891 | } else { | ||
1892 | dictlen++; | ||
1893 | dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, | ||
1894 | "DEVICE=+%s:%s", subsys, dev_name(dev)); | ||
1895 | } | ||
1896 | skip: | ||
1897 | return printk_emit(0, level[1] - '0', | ||
1898 | dictlen ? dict : NULL, dictlen, | ||
1899 | "%s %s: %pV", | ||
1900 | dev_driver_string(dev), dev_name(dev), vaf); | ||
1855 | } | 1901 | } |
1856 | EXPORT_SYMBOL(__dev_printk); | 1902 | EXPORT_SYMBOL(__dev_printk); |
1857 | 1903 | ||
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 524bf96c289f..2360adb7a58f 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c | |||
@@ -309,6 +309,10 @@ EXPORT_SYMBOL_GPL(devres_remove); | |||
309 | * which @match returns 1. If @match is NULL, it's considered to | 309 | * which @match returns 1. If @match is NULL, it's considered to |
310 | * match all. If found, the resource is removed atomically and freed. | 310 | * match all. If found, the resource is removed atomically and freed. |
311 | * | 311 | * |
312 | * Note that the release function for the resource will not be called, | ||
313 | * only the devres-allocated data will be freed. The caller becomes | ||
314 | * responsible for freeing any other data. | ||
315 | * | ||
312 | * RETURNS: | 316 | * RETURNS: |
313 | * 0 if devres is found and freed, -ENOENT if not found. | 317 | * 0 if devres is found and freed, -ENOENT if not found. |
314 | */ | 318 | */ |
@@ -326,6 +330,37 @@ int devres_destroy(struct device *dev, dr_release_t release, | |||
326 | } | 330 | } |
327 | EXPORT_SYMBOL_GPL(devres_destroy); | 331 | EXPORT_SYMBOL_GPL(devres_destroy); |
328 | 332 | ||
333 | |||
334 | /** | ||
335 | * devres_release - Find a device resource and destroy it, calling release | ||
336 | * @dev: Device to find resource from | ||
337 | * @release: Look for resources associated with this release function | ||
338 | * @match: Match function (optional) | ||
339 | * @match_data: Data for the match function | ||
340 | * | ||
341 | * Find the latest devres of @dev associated with @release and for | ||
342 | * which @match returns 1. If @match is NULL, it's considered to | ||
343 | * match all. If found, the resource is removed atomically, the | ||
344 | * release function called and the resource freed. | ||
345 | * | ||
346 | * RETURNS: | ||
347 | * 0 if devres is found and freed, -ENOENT if not found. | ||
348 | */ | ||
349 | int devres_release(struct device *dev, dr_release_t release, | ||
350 | dr_match_t match, void *match_data) | ||
351 | { | ||
352 | void *res; | ||
353 | |||
354 | res = devres_remove(dev, release, match, match_data); | ||
355 | if (unlikely(!res)) | ||
356 | return -ENOENT; | ||
357 | |||
358 | (*release)(dev, res); | ||
359 | devres_free(res); | ||
360 | return 0; | ||
361 | } | ||
362 | EXPORT_SYMBOL_GPL(devres_release); | ||
363 | |||
329 | static int remove_nodes(struct device *dev, | 364 | static int remove_nodes(struct device *dev, |
330 | struct list_head *first, struct list_head *end, | 365 | struct list_head *first, struct list_head *end, |
331 | struct list_head *todo) | 366 | struct list_head *todo) |
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 8493536ea55b..765c3a28077a 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
@@ -7,9 +7,9 @@ | |||
7 | * devtmpfs, a tmpfs-based filesystem is created. Every driver-core | 7 | * devtmpfs, a tmpfs-based filesystem is created. Every driver-core |
8 | * device which requests a device node, will add a node in this | 8 | * device which requests a device node, will add a node in this |
9 | * filesystem. | 9 | * filesystem. |
10 | * By default, all devices are named after the the name of the | 10 | * By default, all devices are named after the name of the device, |
11 | * device, owned by root and have a default mode of 0600. Subsystems | 11 | * owned by root and have a default mode of 0600. Subsystems can |
12 | * can overwrite the default setting if needed. | 12 | * overwrite the default setting if needed. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 07cbbc6fddb4..05c64c11bad2 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c | |||
@@ -293,7 +293,7 @@ EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); | |||
293 | * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific | 293 | * cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific |
294 | * preparations. Coherency is only guaranteed in the specified range for the | 294 | * preparations. Coherency is only guaranteed in the specified range for the |
295 | * specified access direction. | 295 | * specified access direction. |
296 | * @dma_buf: [in] buffer to prepare cpu access for. | 296 | * @dmabuf: [in] buffer to prepare cpu access for. |
297 | * @start: [in] start of range for cpu access. | 297 | * @start: [in] start of range for cpu access. |
298 | * @len: [in] length of range for cpu access. | 298 | * @len: [in] length of range for cpu access. |
299 | * @direction: [in] length of range for cpu access. | 299 | * @direction: [in] length of range for cpu access. |
@@ -320,7 +320,7 @@ EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); | |||
320 | * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific | 320 | * cpu in the kernel context. Calls end_cpu_access to allow exporter-specific |
321 | * actions. Coherency is only guaranteed in the specified range for the | 321 | * actions. Coherency is only guaranteed in the specified range for the |
322 | * specified access direction. | 322 | * specified access direction. |
323 | * @dma_buf: [in] buffer to complete cpu access for. | 323 | * @dmabuf: [in] buffer to complete cpu access for. |
324 | * @start: [in] start of range for cpu access. | 324 | * @start: [in] start of range for cpu access. |
325 | * @len: [in] length of range for cpu access. | 325 | * @len: [in] length of range for cpu access. |
326 | * @direction: [in] length of range for cpu access. | 326 | * @direction: [in] length of range for cpu access. |
@@ -340,7 +340,7 @@ EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access); | |||
340 | /** | 340 | /** |
341 | * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address | 341 | * dma_buf_kmap_atomic - Map a page of the buffer object into kernel address |
342 | * space. The same restrictions as for kmap_atomic and friends apply. | 342 | * space. The same restrictions as for kmap_atomic and friends apply. |
343 | * @dma_buf: [in] buffer to map page from. | 343 | * @dmabuf: [in] buffer to map page from. |
344 | * @page_num: [in] page in PAGE_SIZE units to map. | 344 | * @page_num: [in] page in PAGE_SIZE units to map. |
345 | * | 345 | * |
346 | * This call must always succeed, any necessary preparations that might fail | 346 | * This call must always succeed, any necessary preparations that might fail |
@@ -356,7 +356,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic); | |||
356 | 356 | ||
357 | /** | 357 | /** |
358 | * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic. | 358 | * dma_buf_kunmap_atomic - Unmap a page obtained by dma_buf_kmap_atomic. |
359 | * @dma_buf: [in] buffer to unmap page from. | 359 | * @dmabuf: [in] buffer to unmap page from. |
360 | * @page_num: [in] page in PAGE_SIZE units to unmap. | 360 | * @page_num: [in] page in PAGE_SIZE units to unmap. |
361 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap_atomic. | 361 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap_atomic. |
362 | * | 362 | * |
@@ -375,7 +375,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic); | |||
375 | /** | 375 | /** |
376 | * dma_buf_kmap - Map a page of the buffer object into kernel address space. The | 376 | * dma_buf_kmap - Map a page of the buffer object into kernel address space. The |
377 | * same restrictions as for kmap and friends apply. | 377 | * same restrictions as for kmap and friends apply. |
378 | * @dma_buf: [in] buffer to map page from. | 378 | * @dmabuf: [in] buffer to map page from. |
379 | * @page_num: [in] page in PAGE_SIZE units to map. | 379 | * @page_num: [in] page in PAGE_SIZE units to map. |
380 | * | 380 | * |
381 | * This call must always succeed, any necessary preparations that might fail | 381 | * This call must always succeed, any necessary preparations that might fail |
@@ -391,7 +391,7 @@ EXPORT_SYMBOL_GPL(dma_buf_kmap); | |||
391 | 391 | ||
392 | /** | 392 | /** |
393 | * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap. | 393 | * dma_buf_kunmap - Unmap a page obtained by dma_buf_kmap. |
394 | * @dma_buf: [in] buffer to unmap page from. | 394 | * @dmabuf: [in] buffer to unmap page from. |
395 | * @page_num: [in] page in PAGE_SIZE units to unmap. | 395 | * @page_num: [in] page in PAGE_SIZE units to unmap. |
396 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap. | 396 | * @vaddr: [in] kernel space pointer obtained from dma_buf_kmap. |
397 | * | 397 | * |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 3ec3896c83a6..207c27ddf828 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -80,7 +80,7 @@ struct device *driver_find_device(struct device_driver *drv, | |||
80 | struct klist_iter i; | 80 | struct klist_iter i; |
81 | struct device *dev; | 81 | struct device *dev; |
82 | 82 | ||
83 | if (!drv) | 83 | if (!drv || !drv->p) |
84 | return NULL; | 84 | return NULL; |
85 | 85 | ||
86 | klist_iter_init_node(&drv->p->klist_devices, &i, | 86 | klist_iter_init_node(&drv->p->klist_devices, &i, |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index d6e9d081c8b1..67c3371723cc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -807,44 +807,6 @@ static const struct file_operations oldmem_fops = { | |||
807 | }; | 807 | }; |
808 | #endif | 808 | #endif |
809 | 809 | ||
810 | static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv, | ||
811 | unsigned long count, loff_t pos) | ||
812 | { | ||
813 | char *line, *p; | ||
814 | int i; | ||
815 | ssize_t ret = -EFAULT; | ||
816 | size_t len = iov_length(iv, count); | ||
817 | |||
818 | line = kmalloc(len + 1, GFP_KERNEL); | ||
819 | if (line == NULL) | ||
820 | return -ENOMEM; | ||
821 | |||
822 | /* | ||
823 | * copy all vectors into a single string, to ensure we do | ||
824 | * not interleave our log line with other printk calls | ||
825 | */ | ||
826 | p = line; | ||
827 | for (i = 0; i < count; i++) { | ||
828 | if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len)) | ||
829 | goto out; | ||
830 | p += iv[i].iov_len; | ||
831 | } | ||
832 | p[0] = '\0'; | ||
833 | |||
834 | ret = printk("%s", line); | ||
835 | /* printk can add a prefix */ | ||
836 | if (ret > len) | ||
837 | ret = len; | ||
838 | out: | ||
839 | kfree(line); | ||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | static const struct file_operations kmsg_fops = { | ||
844 | .aio_write = kmsg_writev, | ||
845 | .llseek = noop_llseek, | ||
846 | }; | ||
847 | |||
848 | static const struct memdev { | 810 | static const struct memdev { |
849 | const char *name; | 811 | const char *name; |
850 | umode_t mode; | 812 | umode_t mode; |
@@ -863,7 +825,9 @@ static const struct memdev { | |||
863 | [7] = { "full", 0666, &full_fops, NULL }, | 825 | [7] = { "full", 0666, &full_fops, NULL }, |
864 | [8] = { "random", 0666, &random_fops, NULL }, | 826 | [8] = { "random", 0666, &random_fops, NULL }, |
865 | [9] = { "urandom", 0666, &urandom_fops, NULL }, | 827 | [9] = { "urandom", 0666, &urandom_fops, NULL }, |
866 | [11] = { "kmsg", 0, &kmsg_fops, NULL }, | 828 | #ifdef CONFIG_PRINTK |
829 | [11] = { "kmsg", 0644, &kmsg_fops, NULL }, | ||
830 | #endif | ||
867 | #ifdef CONFIG_CRASH_DUMP | 831 | #ifdef CONFIG_CRASH_DUMP |
868 | [12] = { "oldmem", 0, &oldmem_fops, NULL }, | 832 | [12] = { "oldmem", 0, &oldmem_fops, NULL }, |
869 | #endif | 833 | #endif |
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig new file mode 100644 index 000000000000..29c5cf852efc --- /dev/null +++ b/drivers/extcon/Kconfig | |||
@@ -0,0 +1,32 @@ | |||
1 | menuconfig EXTCON | ||
2 | tristate "External Connector Class (extcon) support" | ||
3 | help | ||
4 | Say Y here to enable external connector class (extcon) support. | ||
5 | This allows monitoring external connectors by userspace | ||
6 | via sysfs and uevent and supports external connectors with | ||
7 | multiple states; i.e., an extcon that may have multiple | ||
8 | cables attached. For example, an external connector of a device | ||
9 | may be used to connect an HDMI cable and a AC adaptor, and to | ||
10 | host USB ports. Many of 30-pin connectors including PDMI are | ||
11 | also good examples. | ||
12 | |||
13 | if EXTCON | ||
14 | |||
15 | comment "Extcon Device Drivers" | ||
16 | |||
17 | config EXTCON_GPIO | ||
18 | tristate "GPIO extcon support" | ||
19 | depends on GENERIC_GPIO | ||
20 | help | ||
21 | Say Y here to enable GPIO based extcon support. Note that GPIO | ||
22 | extcon supports single state per extcon instance. | ||
23 | |||
24 | config EXTCON_MAX8997 | ||
25 | tristate "MAX8997 EXTCON Support" | ||
26 | depends on MFD_MAX8997 | ||
27 | help | ||
28 | If you say yes here you get support for the MUIC device of | ||
29 | Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory | ||
30 | detector and switch. | ||
31 | |||
32 | endif # MULTISTATE_SWITCH | ||
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile new file mode 100644 index 000000000000..86020bdb6da0 --- /dev/null +++ b/drivers/extcon/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for external connector class (extcon) devices | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_EXTCON) += extcon_class.o | ||
6 | obj-$(CONFIG_EXTCON_GPIO) += extcon_gpio.o | ||
7 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o | ||
diff --git a/drivers/misc/max8997-muic.c b/drivers/extcon/extcon-max8997.c index 2e7df9c56491..23416e443765 100644 --- a/drivers/misc/max8997-muic.c +++ b/drivers/extcon/extcon-max8997.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * max8997-muic.c - MAX8997 muic driver for the Maxim 8997 | 2 | * extcon-max8997.c - MAX8997 extcon driver to support MAX8997 MUIC |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Samsung Electrnoics | 4 | * Copyright (C) 2012 Samsung Electrnoics |
5 | * Donggeun Kim <dg77.kim@samsung.com> | 5 | * Donggeun Kim <dg77.kim@samsung.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -13,11 +13,6 @@ | |||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | 16 | */ |
22 | 17 | ||
23 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -30,6 +25,9 @@ | |||
30 | #include <linux/kobject.h> | 25 | #include <linux/kobject.h> |
31 | #include <linux/mfd/max8997.h> | 26 | #include <linux/mfd/max8997.h> |
32 | #include <linux/mfd/max8997-private.h> | 27 | #include <linux/mfd/max8997-private.h> |
28 | #include <linux/extcon.h> | ||
29 | |||
30 | #define DEV_NAME "max8997-muic" | ||
33 | 31 | ||
34 | /* MAX8997-MUIC STATUS1 register */ | 32 | /* MAX8997-MUIC STATUS1 register */ |
35 | #define STATUS1_ADC_SHIFT 0 | 33 | #define STATUS1_ADC_SHIFT 0 |
@@ -95,7 +93,6 @@ static struct max8997_muic_irq muic_irqs[] = { | |||
95 | 93 | ||
96 | struct max8997_muic_info { | 94 | struct max8997_muic_info { |
97 | struct device *dev; | 95 | struct device *dev; |
98 | struct max8997_dev *iodev; | ||
99 | struct i2c_client *muic; | 96 | struct i2c_client *muic; |
100 | struct max8997_muic_platform_data *muic_pdata; | 97 | struct max8997_muic_platform_data *muic_pdata; |
101 | 98 | ||
@@ -106,12 +103,28 @@ struct max8997_muic_info { | |||
106 | int pre_adc; | 103 | int pre_adc; |
107 | 104 | ||
108 | struct mutex mutex; | 105 | struct mutex mutex; |
106 | |||
107 | struct extcon_dev *edev; | ||
108 | }; | ||
109 | |||
110 | const char *max8997_extcon_cable[] = { | ||
111 | [0] = "USB", | ||
112 | [1] = "USB-Host", | ||
113 | [2] = "TA", | ||
114 | [3] = "Fast-charger", | ||
115 | [4] = "Slow-charger", | ||
116 | [5] = "Charge-downstream", | ||
117 | [6] = "MHL", | ||
118 | [7] = "Dock-desk", | ||
119 | [7] = "Dock-card", | ||
120 | [8] = "JIG", | ||
121 | |||
122 | NULL, | ||
109 | }; | 123 | }; |
110 | 124 | ||
111 | static int max8997_muic_handle_usb(struct max8997_muic_info *info, | 125 | static int max8997_muic_handle_usb(struct max8997_muic_info *info, |
112 | enum max8997_muic_usb_type usb_type, bool attached) | 126 | enum max8997_muic_usb_type usb_type, bool attached) |
113 | { | 127 | { |
114 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
115 | int ret = 0; | 128 | int ret = 0; |
116 | 129 | ||
117 | if (usb_type == MAX8997_USB_HOST) { | 130 | if (usb_type == MAX8997_USB_HOST) { |
@@ -125,25 +138,25 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info, | |||
125 | } | 138 | } |
126 | } | 139 | } |
127 | 140 | ||
128 | if (mdata->usb_callback) | 141 | switch (usb_type) { |
129 | mdata->usb_callback(usb_type, attached); | 142 | case MAX8997_USB_HOST: |
143 | extcon_set_cable_state(info->edev, "USB-Host", attached); | ||
144 | break; | ||
145 | case MAX8997_USB_DEVICE: | ||
146 | extcon_set_cable_state(info->edev, "USB", attached); | ||
147 | break; | ||
148 | default: | ||
149 | ret = -EINVAL; | ||
150 | break; | ||
151 | } | ||
152 | |||
130 | out: | 153 | out: |
131 | return ret; | 154 | return ret; |
132 | } | 155 | } |
133 | 156 | ||
134 | static void max8997_muic_handle_mhl(struct max8997_muic_info *info, | ||
135 | bool attached) | ||
136 | { | ||
137 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
138 | |||
139 | if (mdata->mhl_callback) | ||
140 | mdata->mhl_callback(attached); | ||
141 | } | ||
142 | |||
143 | static int max8997_muic_handle_dock(struct max8997_muic_info *info, | 157 | static int max8997_muic_handle_dock(struct max8997_muic_info *info, |
144 | int adc, bool attached) | 158 | int adc, bool attached) |
145 | { | 159 | { |
146 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
147 | int ret = 0; | 160 | int ret = 0; |
148 | 161 | ||
149 | /* switch to AUDIO */ | 162 | /* switch to AUDIO */ |
@@ -157,14 +170,13 @@ static int max8997_muic_handle_dock(struct max8997_muic_info *info, | |||
157 | 170 | ||
158 | switch (adc) { | 171 | switch (adc) { |
159 | case MAX8997_ADC_DESKDOCK: | 172 | case MAX8997_ADC_DESKDOCK: |
160 | if (mdata->deskdock_callback) | 173 | extcon_set_cable_state(info->edev, "Dock-desk", attached); |
161 | mdata->deskdock_callback(attached); | ||
162 | break; | 174 | break; |
163 | case MAX8997_ADC_CARDOCK: | 175 | case MAX8997_ADC_CARDOCK: |
164 | if (mdata->cardock_callback) | 176 | extcon_set_cable_state(info->edev, "Dock-card", attached); |
165 | mdata->cardock_callback(attached); | ||
166 | break; | 177 | break; |
167 | default: | 178 | default: |
179 | ret = -EINVAL; | ||
168 | break; | 180 | break; |
169 | } | 181 | } |
170 | out: | 182 | out: |
@@ -174,7 +186,6 @@ out: | |||
174 | static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info, | 186 | static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info, |
175 | bool attached) | 187 | bool attached) |
176 | { | 188 | { |
177 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
178 | int ret = 0; | 189 | int ret = 0; |
179 | 190 | ||
180 | /* switch to UART */ | 191 | /* switch to UART */ |
@@ -186,8 +197,7 @@ static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info, | |||
186 | goto out; | 197 | goto out; |
187 | } | 198 | } |
188 | 199 | ||
189 | if (mdata->uart_callback) | 200 | extcon_set_cable_state(info->edev, "JIG", attached); |
190 | mdata->uart_callback(attached); | ||
191 | out: | 201 | out: |
192 | return ret; | 202 | return ret; |
193 | } | 203 | } |
@@ -201,7 +211,7 @@ static int max8997_muic_handle_adc_detach(struct max8997_muic_info *info) | |||
201 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false); | 211 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false); |
202 | break; | 212 | break; |
203 | case MAX8997_ADC_MHL: | 213 | case MAX8997_ADC_MHL: |
204 | max8997_muic_handle_mhl(info, false); | 214 | extcon_set_cable_state(info->edev, "MHL", false); |
205 | break; | 215 | break; |
206 | case MAX8997_ADC_JIG_USB_1: | 216 | case MAX8997_ADC_JIG_USB_1: |
207 | case MAX8997_ADC_JIG_USB_2: | 217 | case MAX8997_ADC_JIG_USB_2: |
@@ -230,7 +240,7 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) | |||
230 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true); | 240 | ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true); |
231 | break; | 241 | break; |
232 | case MAX8997_ADC_MHL: | 242 | case MAX8997_ADC_MHL: |
233 | max8997_muic_handle_mhl(info, true); | 243 | extcon_set_cable_state(info->edev, "MHL", true); |
234 | break; | 244 | break; |
235 | case MAX8997_ADC_JIG_USB_1: | 245 | case MAX8997_ADC_JIG_USB_1: |
236 | case MAX8997_ADC_JIG_USB_2: | 246 | case MAX8997_ADC_JIG_USB_2: |
@@ -247,10 +257,40 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) | |||
247 | ret = max8997_muic_handle_adc_detach(info); | 257 | ret = max8997_muic_handle_adc_detach(info); |
248 | break; | 258 | break; |
249 | default: | 259 | default: |
250 | break; | 260 | ret = -EINVAL; |
261 | goto out; | ||
251 | } | 262 | } |
252 | 263 | ||
253 | info->pre_adc = adc; | 264 | info->pre_adc = adc; |
265 | out: | ||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | static int max8997_muic_handle_charger_type_detach( | ||
270 | struct max8997_muic_info *info) | ||
271 | { | ||
272 | int ret = 0; | ||
273 | |||
274 | switch (info->pre_charger_type) { | ||
275 | case MAX8997_CHARGER_TYPE_USB: | ||
276 | extcon_set_cable_state(info->edev, "USB", false); | ||
277 | break; | ||
278 | case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: | ||
279 | extcon_set_cable_state(info->edev, "Charge-downstream", false); | ||
280 | break; | ||
281 | case MAX8997_CHARGER_TYPE_DEDICATED_CHG: | ||
282 | extcon_set_cable_state(info->edev, "TA", false); | ||
283 | break; | ||
284 | case MAX8997_CHARGER_TYPE_500MA: | ||
285 | extcon_set_cable_state(info->edev, "Slow-charger", false); | ||
286 | break; | ||
287 | case MAX8997_CHARGER_TYPE_1A: | ||
288 | extcon_set_cable_state(info->edev, "Fast-charger", false); | ||
289 | break; | ||
290 | default: | ||
291 | ret = -EINVAL; | ||
292 | break; | ||
293 | } | ||
254 | 294 | ||
255 | return ret; | 295 | return ret; |
256 | } | 296 | } |
@@ -258,7 +298,6 @@ static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc) | |||
258 | static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, | 298 | static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, |
259 | enum max8997_muic_charger_type charger_type) | 299 | enum max8997_muic_charger_type charger_type) |
260 | { | 300 | { |
261 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
262 | u8 adc; | 301 | u8 adc; |
263 | int ret; | 302 | int ret; |
264 | 303 | ||
@@ -270,30 +309,29 @@ static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, | |||
270 | 309 | ||
271 | switch (charger_type) { | 310 | switch (charger_type) { |
272 | case MAX8997_CHARGER_TYPE_NONE: | 311 | case MAX8997_CHARGER_TYPE_NONE: |
273 | if (mdata->charger_callback) | 312 | ret = max8997_muic_handle_charger_type_detach(info); |
274 | mdata->charger_callback(false, charger_type); | ||
275 | if (info->pre_charger_type == MAX8997_CHARGER_TYPE_USB) { | ||
276 | max8997_muic_handle_usb(info, | ||
277 | MAX8997_USB_DEVICE, false); | ||
278 | } | ||
279 | break; | 313 | break; |
280 | case MAX8997_CHARGER_TYPE_USB: | 314 | case MAX8997_CHARGER_TYPE_USB: |
281 | if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) { | 315 | if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) { |
282 | max8997_muic_handle_usb(info, | 316 | max8997_muic_handle_usb(info, |
283 | MAX8997_USB_DEVICE, true); | 317 | MAX8997_USB_DEVICE, true); |
284 | } | 318 | } |
285 | if (mdata->charger_callback) | ||
286 | mdata->charger_callback(true, charger_type); | ||
287 | break; | 319 | break; |
288 | case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: | 320 | case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT: |
321 | extcon_set_cable_state(info->edev, "Charge-downstream", true); | ||
322 | break; | ||
289 | case MAX8997_CHARGER_TYPE_DEDICATED_CHG: | 323 | case MAX8997_CHARGER_TYPE_DEDICATED_CHG: |
324 | extcon_set_cable_state(info->edev, "TA", true); | ||
325 | break; | ||
290 | case MAX8997_CHARGER_TYPE_500MA: | 326 | case MAX8997_CHARGER_TYPE_500MA: |
327 | extcon_set_cable_state(info->edev, "Slow-charger", true); | ||
328 | break; | ||
291 | case MAX8997_CHARGER_TYPE_1A: | 329 | case MAX8997_CHARGER_TYPE_1A: |
292 | if (mdata->charger_callback) | 330 | extcon_set_cable_state(info->edev, "Fast-charger", true); |
293 | mdata->charger_callback(true, charger_type); | ||
294 | break; | 331 | break; |
295 | default: | 332 | default: |
296 | break; | 333 | ret = -EINVAL; |
334 | goto out; | ||
297 | } | 335 | } |
298 | 336 | ||
299 | info->pre_charger_type = charger_type; | 337 | info->pre_charger_type = charger_type; |
@@ -305,18 +343,17 @@ static void max8997_muic_irq_work(struct work_struct *work) | |||
305 | { | 343 | { |
306 | struct max8997_muic_info *info = container_of(work, | 344 | struct max8997_muic_info *info = container_of(work, |
307 | struct max8997_muic_info, irq_work); | 345 | struct max8997_muic_info, irq_work); |
308 | struct max8997_platform_data *pdata = | 346 | struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); |
309 | dev_get_platdata(info->iodev->dev); | 347 | u8 status[2]; |
310 | u8 status[3]; | ||
311 | u8 adc, chg_type; | 348 | u8 adc, chg_type; |
312 | 349 | ||
313 | int irq_type = info->irq - pdata->irq_base; | 350 | int irq_type = info->irq - max8997->irq_base; |
314 | int ret; | 351 | int ret; |
315 | 352 | ||
316 | mutex_lock(&info->mutex); | 353 | mutex_lock(&info->mutex); |
317 | 354 | ||
318 | ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, | 355 | ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1, |
319 | 3, status); | 356 | 2, status); |
320 | if (ret) { | 357 | if (ret) { |
321 | dev_err(info->dev, "failed to read muic register\n"); | 358 | dev_err(info->dev, "failed to read muic register\n"); |
322 | mutex_unlock(&info->mutex); | 359 | mutex_unlock(&info->mutex); |
@@ -340,8 +377,8 @@ static void max8997_muic_irq_work(struct work_struct *work) | |||
340 | max8997_muic_handle_charger_type(info, chg_type); | 377 | max8997_muic_handle_charger_type(info, chg_type); |
341 | break; | 378 | break; |
342 | default: | 379 | default: |
343 | dev_info(info->dev, "misc interrupt: %s occurred\n", | 380 | dev_info(info->dev, "misc interrupt: irq %d occurred\n", |
344 | muic_irqs[irq_type].name); | 381 | irq_type); |
345 | break; | 382 | break; |
346 | } | 383 | } |
347 | 384 | ||
@@ -387,21 +424,10 @@ static void max8997_muic_detect_dev(struct max8997_muic_info *info) | |||
387 | max8997_muic_handle_charger_type(info, chg_type); | 424 | max8997_muic_handle_charger_type(info, chg_type); |
388 | } | 425 | } |
389 | 426 | ||
390 | static void max8997_initialize_device(struct max8997_muic_info *info) | ||
391 | { | ||
392 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
393 | int i; | ||
394 | |||
395 | for (i = 0; i < mdata->num_init_data; i++) { | ||
396 | max8997_write_reg(info->muic, mdata->init_data[i].addr, | ||
397 | mdata->init_data[i].data); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | static int __devinit max8997_muic_probe(struct platform_device *pdev) | 427 | static int __devinit max8997_muic_probe(struct platform_device *pdev) |
402 | { | 428 | { |
403 | struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 429 | struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent); |
404 | struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); | 430 | struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev); |
405 | struct max8997_muic_info *info; | 431 | struct max8997_muic_info *info; |
406 | int ret, i; | 432 | int ret, i; |
407 | 433 | ||
@@ -412,16 +438,8 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev) | |||
412 | goto err_kfree; | 438 | goto err_kfree; |
413 | } | 439 | } |
414 | 440 | ||
415 | if (!pdata->muic_pdata) { | ||
416 | dev_err(&pdev->dev, "failed to get platform_data\n"); | ||
417 | ret = -EINVAL; | ||
418 | goto err_pdata; | ||
419 | } | ||
420 | info->muic_pdata = pdata->muic_pdata; | ||
421 | |||
422 | info->dev = &pdev->dev; | 441 | info->dev = &pdev->dev; |
423 | info->iodev = iodev; | 442 | info->muic = max8997->muic; |
424 | info->muic = iodev->muic; | ||
425 | 443 | ||
426 | platform_set_drvdata(pdev, info); | 444 | platform_set_drvdata(pdev, info); |
427 | mutex_init(&info->mutex); | 445 | mutex_init(&info->mutex); |
@@ -444,18 +462,41 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev) | |||
444 | } | 462 | } |
445 | } | 463 | } |
446 | 464 | ||
465 | /* External connector */ | ||
466 | info->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL); | ||
467 | if (!info->edev) { | ||
468 | dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); | ||
469 | ret = -ENOMEM; | ||
470 | goto err_irq; | ||
471 | } | ||
472 | info->edev->name = DEV_NAME; | ||
473 | info->edev->supported_cable = max8997_extcon_cable; | ||
474 | ret = extcon_dev_register(info->edev, NULL); | ||
475 | if (ret) { | ||
476 | dev_err(&pdev->dev, "failed to register extcon device\n"); | ||
477 | goto err_extcon; | ||
478 | } | ||
479 | |||
447 | /* Initialize registers according to platform data */ | 480 | /* Initialize registers according to platform data */ |
448 | max8997_initialize_device(info); | 481 | if (pdata->muic_pdata) { |
482 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | ||
483 | |||
484 | for (i = 0; i < mdata->num_init_data; i++) { | ||
485 | max8997_write_reg(info->muic, mdata->init_data[i].addr, | ||
486 | mdata->init_data[i].data); | ||
487 | } | ||
488 | } | ||
449 | 489 | ||
450 | /* Initial device detection */ | 490 | /* Initial device detection */ |
451 | max8997_muic_detect_dev(info); | 491 | max8997_muic_detect_dev(info); |
452 | 492 | ||
453 | return ret; | 493 | return ret; |
454 | 494 | ||
495 | err_extcon: | ||
496 | kfree(info->edev); | ||
455 | err_irq: | 497 | err_irq: |
456 | while (--i >= 0) | 498 | while (--i >= 0) |
457 | free_irq(pdata->irq_base + muic_irqs[i].irq, info); | 499 | free_irq(pdata->irq_base + muic_irqs[i].irq, info); |
458 | err_pdata: | ||
459 | kfree(info); | 500 | kfree(info); |
460 | err_kfree: | 501 | err_kfree: |
461 | return ret; | 502 | return ret; |
@@ -464,14 +505,15 @@ err_kfree: | |||
464 | static int __devexit max8997_muic_remove(struct platform_device *pdev) | 505 | static int __devexit max8997_muic_remove(struct platform_device *pdev) |
465 | { | 506 | { |
466 | struct max8997_muic_info *info = platform_get_drvdata(pdev); | 507 | struct max8997_muic_info *info = platform_get_drvdata(pdev); |
467 | struct max8997_platform_data *pdata = | 508 | struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); |
468 | dev_get_platdata(info->iodev->dev); | ||
469 | int i; | 509 | int i; |
470 | 510 | ||
471 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) | 511 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) |
472 | free_irq(pdata->irq_base + muic_irqs[i].irq, info); | 512 | free_irq(max8997->irq_base + muic_irqs[i].irq, info); |
473 | cancel_work_sync(&info->irq_work); | 513 | cancel_work_sync(&info->irq_work); |
474 | 514 | ||
515 | extcon_dev_unregister(info->edev); | ||
516 | |||
475 | kfree(info); | 517 | kfree(info); |
476 | 518 | ||
477 | return 0; | 519 | return 0; |
@@ -479,7 +521,7 @@ static int __devexit max8997_muic_remove(struct platform_device *pdev) | |||
479 | 521 | ||
480 | static struct platform_driver max8997_muic_driver = { | 522 | static struct platform_driver max8997_muic_driver = { |
481 | .driver = { | 523 | .driver = { |
482 | .name = "max8997-muic", | 524 | .name = DEV_NAME, |
483 | .owner = THIS_MODULE, | 525 | .owner = THIS_MODULE, |
484 | }, | 526 | }, |
485 | .probe = max8997_muic_probe, | 527 | .probe = max8997_muic_probe, |
@@ -488,6 +530,6 @@ static struct platform_driver max8997_muic_driver = { | |||
488 | 530 | ||
489 | module_platform_driver(max8997_muic_driver); | 531 | module_platform_driver(max8997_muic_driver); |
490 | 532 | ||
491 | MODULE_DESCRIPTION("Maxim MAX8997 MUIC driver"); | 533 | MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver"); |
492 | MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); | 534 | MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); |
493 | MODULE_LICENSE("GPL"); | 535 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c new file mode 100644 index 000000000000..f598a700ec15 --- /dev/null +++ b/drivers/extcon/extcon_class.c | |||
@@ -0,0 +1,832 @@ | |||
1 | /* | ||
2 | * drivers/extcon/extcon_class.c | ||
3 | * | ||
4 | * External connector (extcon) class driver | ||
5 | * | ||
6 | * Copyright (C) 2012 Samsung Electronics | ||
7 | * Author: Donggeun Kim <dg77.kim@samsung.com> | ||
8 | * Author: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
9 | * | ||
10 | * based on android/drivers/switch/switch_class.c | ||
11 | * Copyright (C) 2008 Google, Inc. | ||
12 | * Author: Mike Lockwood <lockwood@android.com> | ||
13 | * | ||
14 | * This software is licensed under the terms of the GNU General Public | ||
15 | * License version 2, as published by the Free Software Foundation, and | ||
16 | * may be copied, distributed, and modified under those terms. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/fs.h> | ||
30 | #include <linux/err.h> | ||
31 | #include <linux/extcon.h> | ||
32 | #include <linux/slab.h> | ||
33 | |||
34 | /* | ||
35 | * extcon_cable_name suggests the standard cable names for commonly used | ||
36 | * cable types. | ||
37 | * | ||
38 | * However, please do not use extcon_cable_name directly for extcon_dev | ||
39 | * struct's supported_cable pointer unless your device really supports | ||
40 | * every single port-type of the following cable names. Please choose cable | ||
41 | * names that are actually used in your extcon device. | ||
42 | */ | ||
43 | const char *extcon_cable_name[] = { | ||
44 | [EXTCON_USB] = "USB", | ||
45 | [EXTCON_USB_HOST] = "USB-Host", | ||
46 | [EXTCON_TA] = "TA", | ||
47 | [EXTCON_FAST_CHARGER] = "Fast-charger", | ||
48 | [EXTCON_SLOW_CHARGER] = "Slow-charger", | ||
49 | [EXTCON_CHARGE_DOWNSTREAM] = "Charge-downstream", | ||
50 | [EXTCON_HDMI] = "HDMI", | ||
51 | [EXTCON_MHL] = "MHL", | ||
52 | [EXTCON_DVI] = "DVI", | ||
53 | [EXTCON_VGA] = "VGA", | ||
54 | [EXTCON_DOCK] = "Dock", | ||
55 | [EXTCON_LINE_IN] = "Line-in", | ||
56 | [EXTCON_LINE_OUT] = "Line-out", | ||
57 | [EXTCON_MIC_IN] = "Microphone", | ||
58 | [EXTCON_HEADPHONE_OUT] = "Headphone", | ||
59 | [EXTCON_SPDIF_IN] = "SPDIF-in", | ||
60 | [EXTCON_SPDIF_OUT] = "SPDIF-out", | ||
61 | [EXTCON_VIDEO_IN] = "Video-in", | ||
62 | [EXTCON_VIDEO_OUT] = "Video-out", | ||
63 | [EXTCON_MECHANICAL] = "Mechanical", | ||
64 | |||
65 | NULL, | ||
66 | }; | ||
67 | |||
68 | struct class *extcon_class; | ||
69 | #if defined(CONFIG_ANDROID) | ||
70 | static struct class_compat *switch_class; | ||
71 | #endif /* CONFIG_ANDROID */ | ||
72 | |||
73 | static LIST_HEAD(extcon_dev_list); | ||
74 | static DEFINE_MUTEX(extcon_dev_list_lock); | ||
75 | |||
76 | /** | ||
77 | * check_mutually_exclusive - Check if new_state violates mutually_exclusive | ||
78 | * condition. | ||
79 | * @edev: the extcon device | ||
80 | * @new_state: new cable attach status for @edev | ||
81 | * | ||
82 | * Returns 0 if nothing violates. Returns the index + 1 for the first | ||
83 | * violated condition. | ||
84 | */ | ||
85 | static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state) | ||
86 | { | ||
87 | int i = 0; | ||
88 | |||
89 | if (!edev->mutually_exclusive) | ||
90 | return 0; | ||
91 | |||
92 | for (i = 0; edev->mutually_exclusive[i]; i++) { | ||
93 | int count = 0, j; | ||
94 | u32 correspondants = new_state & edev->mutually_exclusive[i]; | ||
95 | u32 exp = 1; | ||
96 | |||
97 | for (j = 0; j < 32; j++) { | ||
98 | if (exp & correspondants) | ||
99 | count++; | ||
100 | if (count > 1) | ||
101 | return i + 1; | ||
102 | exp <<= 1; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static ssize_t state_show(struct device *dev, struct device_attribute *attr, | ||
110 | char *buf) | ||
111 | { | ||
112 | int i, count = 0; | ||
113 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
114 | |||
115 | if (edev->print_state) { | ||
116 | int ret = edev->print_state(edev, buf); | ||
117 | |||
118 | if (ret >= 0) | ||
119 | return ret; | ||
120 | /* Use default if failed */ | ||
121 | } | ||
122 | |||
123 | if (edev->max_supported == 0) | ||
124 | return sprintf(buf, "%u\n", edev->state); | ||
125 | |||
126 | for (i = 0; i < SUPPORTED_CABLE_MAX; i++) { | ||
127 | if (!edev->supported_cable[i]) | ||
128 | break; | ||
129 | count += sprintf(buf + count, "%s=%d\n", | ||
130 | edev->supported_cable[i], | ||
131 | !!(edev->state & (1 << i))); | ||
132 | } | ||
133 | |||
134 | return count; | ||
135 | } | ||
136 | |||
137 | int extcon_set_state(struct extcon_dev *edev, u32 state); | ||
138 | static ssize_t state_store(struct device *dev, struct device_attribute *attr, | ||
139 | const char *buf, size_t count) | ||
140 | { | ||
141 | u32 state; | ||
142 | ssize_t ret = 0; | ||
143 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
144 | |||
145 | ret = sscanf(buf, "0x%x", &state); | ||
146 | if (ret == 0) | ||
147 | ret = -EINVAL; | ||
148 | else | ||
149 | ret = extcon_set_state(edev, state); | ||
150 | |||
151 | if (ret < 0) | ||
152 | return ret; | ||
153 | |||
154 | return count; | ||
155 | } | ||
156 | |||
157 | static ssize_t name_show(struct device *dev, struct device_attribute *attr, | ||
158 | char *buf) | ||
159 | { | ||
160 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
161 | |||
162 | /* Optional callback given by the user */ | ||
163 | if (edev->print_name) { | ||
164 | int ret = edev->print_name(edev, buf); | ||
165 | if (ret >= 0) | ||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | return sprintf(buf, "%s\n", dev_name(edev->dev)); | ||
170 | } | ||
171 | |||
172 | static ssize_t cable_name_show(struct device *dev, | ||
173 | struct device_attribute *attr, char *buf) | ||
174 | { | ||
175 | struct extcon_cable *cable = container_of(attr, struct extcon_cable, | ||
176 | attr_name); | ||
177 | |||
178 | return sprintf(buf, "%s\n", | ||
179 | cable->edev->supported_cable[cable->cable_index]); | ||
180 | } | ||
181 | |||
182 | static ssize_t cable_state_show(struct device *dev, | ||
183 | struct device_attribute *attr, char *buf) | ||
184 | { | ||
185 | struct extcon_cable *cable = container_of(attr, struct extcon_cable, | ||
186 | attr_state); | ||
187 | |||
188 | return sprintf(buf, "%d\n", | ||
189 | extcon_get_cable_state_(cable->edev, | ||
190 | cable->cable_index)); | ||
191 | } | ||
192 | |||
193 | static ssize_t cable_state_store(struct device *dev, | ||
194 | struct device_attribute *attr, const char *buf, | ||
195 | size_t count) | ||
196 | { | ||
197 | struct extcon_cable *cable = container_of(attr, struct extcon_cable, | ||
198 | attr_state); | ||
199 | int ret, state; | ||
200 | |||
201 | ret = sscanf(buf, "%d", &state); | ||
202 | if (ret == 0) | ||
203 | ret = -EINVAL; | ||
204 | else | ||
205 | ret = extcon_set_cable_state_(cable->edev, cable->cable_index, | ||
206 | state); | ||
207 | |||
208 | if (ret < 0) | ||
209 | return ret; | ||
210 | return count; | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * extcon_update_state() - Update the cable attach states of the extcon device | ||
215 | * only for the masked bits. | ||
216 | * @edev: the extcon device | ||
217 | * @mask: the bit mask to designate updated bits. | ||
218 | * @state: new cable attach status for @edev | ||
219 | * | ||
220 | * Changing the state sends uevent with environment variable containing | ||
221 | * the name of extcon device (envp[0]) and the state output (envp[1]). | ||
222 | * Tizen uses this format for extcon device to get events from ports. | ||
223 | * Android uses this format as well. | ||
224 | * | ||
225 | * Note that the notifier provides which bits are changed in the state | ||
226 | * variable with the val parameter (second) to the callback. | ||
227 | */ | ||
228 | int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) | ||
229 | { | ||
230 | char name_buf[120]; | ||
231 | char state_buf[120]; | ||
232 | char *prop_buf; | ||
233 | char *envp[3]; | ||
234 | int env_offset = 0; | ||
235 | int length; | ||
236 | unsigned long flags; | ||
237 | |||
238 | spin_lock_irqsave(&edev->lock, flags); | ||
239 | |||
240 | if (edev->state != ((edev->state & ~mask) | (state & mask))) { | ||
241 | u32 old_state = edev->state; | ||
242 | |||
243 | if (check_mutually_exclusive(edev, (edev->state & ~mask) | | ||
244 | (state & mask))) { | ||
245 | spin_unlock_irqrestore(&edev->lock, flags); | ||
246 | return -EPERM; | ||
247 | } | ||
248 | |||
249 | edev->state &= ~mask; | ||
250 | edev->state |= state & mask; | ||
251 | |||
252 | raw_notifier_call_chain(&edev->nh, old_state, edev); | ||
253 | |||
254 | /* This could be in interrupt handler */ | ||
255 | prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); | ||
256 | if (prop_buf) { | ||
257 | length = name_show(edev->dev, NULL, prop_buf); | ||
258 | if (length > 0) { | ||
259 | if (prop_buf[length - 1] == '\n') | ||
260 | prop_buf[length - 1] = 0; | ||
261 | snprintf(name_buf, sizeof(name_buf), | ||
262 | "NAME=%s", prop_buf); | ||
263 | envp[env_offset++] = name_buf; | ||
264 | } | ||
265 | length = state_show(edev->dev, NULL, prop_buf); | ||
266 | if (length > 0) { | ||
267 | if (prop_buf[length - 1] == '\n') | ||
268 | prop_buf[length - 1] = 0; | ||
269 | snprintf(state_buf, sizeof(state_buf), | ||
270 | "STATE=%s", prop_buf); | ||
271 | envp[env_offset++] = state_buf; | ||
272 | } | ||
273 | envp[env_offset] = NULL; | ||
274 | /* Unlock early before uevent */ | ||
275 | spin_unlock_irqrestore(&edev->lock, flags); | ||
276 | |||
277 | kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp); | ||
278 | free_page((unsigned long)prop_buf); | ||
279 | } else { | ||
280 | /* Unlock early before uevent */ | ||
281 | spin_unlock_irqrestore(&edev->lock, flags); | ||
282 | |||
283 | dev_err(edev->dev, "out of memory in extcon_set_state\n"); | ||
284 | kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE); | ||
285 | } | ||
286 | } else { | ||
287 | /* No changes */ | ||
288 | spin_unlock_irqrestore(&edev->lock, flags); | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | EXPORT_SYMBOL_GPL(extcon_update_state); | ||
294 | |||
295 | /** | ||
296 | * extcon_set_state() - Set the cable attach states of the extcon device. | ||
297 | * @edev: the extcon device | ||
298 | * @state: new cable attach status for @edev | ||
299 | * | ||
300 | * Note that notifier provides which bits are changed in the state | ||
301 | * variable with the val parameter (second) to the callback. | ||
302 | */ | ||
303 | int extcon_set_state(struct extcon_dev *edev, u32 state) | ||
304 | { | ||
305 | return extcon_update_state(edev, 0xffffffff, state); | ||
306 | } | ||
307 | EXPORT_SYMBOL_GPL(extcon_set_state); | ||
308 | |||
309 | /** | ||
310 | * extcon_find_cable_index() - Get the cable index based on the cable name. | ||
311 | * @edev: the extcon device that has the cable. | ||
312 | * @cable_name: cable name to be searched. | ||
313 | * | ||
314 | * Note that accessing a cable state based on cable_index is faster than | ||
315 | * cable_name because using cable_name induces a loop with strncmp(). | ||
316 | * Thus, when get/set_cable_state is repeatedly used, using cable_index | ||
317 | * is recommended. | ||
318 | */ | ||
319 | int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name) | ||
320 | { | ||
321 | int i; | ||
322 | |||
323 | if (edev->supported_cable) { | ||
324 | for (i = 0; edev->supported_cable[i]; i++) { | ||
325 | if (!strncmp(edev->supported_cable[i], | ||
326 | cable_name, CABLE_NAME_MAX)) | ||
327 | return i; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | return -EINVAL; | ||
332 | } | ||
333 | EXPORT_SYMBOL_GPL(extcon_find_cable_index); | ||
334 | |||
335 | /** | ||
336 | * extcon_get_cable_state_() - Get the status of a specific cable. | ||
337 | * @edev: the extcon device that has the cable. | ||
338 | * @index: cable index that can be retrieved by extcon_find_cable_index(). | ||
339 | */ | ||
340 | int extcon_get_cable_state_(struct extcon_dev *edev, int index) | ||
341 | { | ||
342 | if (index < 0 || (edev->max_supported && edev->max_supported <= index)) | ||
343 | return -EINVAL; | ||
344 | |||
345 | return !!(edev->state & (1 << index)); | ||
346 | } | ||
347 | EXPORT_SYMBOL_GPL(extcon_get_cable_state_); | ||
348 | |||
349 | /** | ||
350 | * extcon_get_cable_state() - Get the status of a specific cable. | ||
351 | * @edev: the extcon device that has the cable. | ||
352 | * @cable_name: cable name. | ||
353 | * | ||
354 | * Note that this is slower than extcon_get_cable_state_. | ||
355 | */ | ||
356 | int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) | ||
357 | { | ||
358 | return extcon_get_cable_state_(edev, extcon_find_cable_index | ||
359 | (edev, cable_name)); | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(extcon_get_cable_state); | ||
362 | |||
363 | /** | ||
364 | * extcon_get_cable_state_() - Set the status of a specific cable. | ||
365 | * @edev: the extcon device that has the cable. | ||
366 | * @index: cable index that can be retrieved by extcon_find_cable_index(). | ||
367 | * @cable_state: the new cable status. The default semantics is | ||
368 | * true: attached / false: detached. | ||
369 | */ | ||
370 | int extcon_set_cable_state_(struct extcon_dev *edev, | ||
371 | int index, bool cable_state) | ||
372 | { | ||
373 | u32 state; | ||
374 | |||
375 | if (index < 0 || (edev->max_supported && edev->max_supported <= index)) | ||
376 | return -EINVAL; | ||
377 | |||
378 | state = cable_state ? (1 << index) : 0; | ||
379 | return extcon_update_state(edev, 1 << index, state); | ||
380 | } | ||
381 | EXPORT_SYMBOL_GPL(extcon_set_cable_state_); | ||
382 | |||
383 | /** | ||
384 | * extcon_get_cable_state() - Set the status of a specific cable. | ||
385 | * @edev: the extcon device that has the cable. | ||
386 | * @cable_name: cable name. | ||
387 | * @cable_state: the new cable status. The default semantics is | ||
388 | * true: attached / false: detached. | ||
389 | * | ||
390 | * Note that this is slower than extcon_set_cable_state_. | ||
391 | */ | ||
392 | int extcon_set_cable_state(struct extcon_dev *edev, | ||
393 | const char *cable_name, bool cable_state) | ||
394 | { | ||
395 | return extcon_set_cable_state_(edev, extcon_find_cable_index | ||
396 | (edev, cable_name), cable_state); | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(extcon_set_cable_state); | ||
399 | |||
400 | /** | ||
401 | * extcon_get_extcon_dev() - Get the extcon device instance from the name | ||
402 | * @extcon_name: The extcon name provided with extcon_dev_register() | ||
403 | */ | ||
404 | struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) | ||
405 | { | ||
406 | struct extcon_dev *sd; | ||
407 | |||
408 | mutex_lock(&extcon_dev_list_lock); | ||
409 | list_for_each_entry(sd, &extcon_dev_list, entry) { | ||
410 | if (!strcmp(sd->name, extcon_name)) | ||
411 | goto out; | ||
412 | } | ||
413 | sd = NULL; | ||
414 | out: | ||
415 | mutex_unlock(&extcon_dev_list_lock); | ||
416 | return sd; | ||
417 | } | ||
418 | EXPORT_SYMBOL_GPL(extcon_get_extcon_dev); | ||
419 | |||
420 | static int _call_per_cable(struct notifier_block *nb, unsigned long val, | ||
421 | void *ptr) | ||
422 | { | ||
423 | struct extcon_specific_cable_nb *obj = container_of(nb, | ||
424 | struct extcon_specific_cable_nb, internal_nb); | ||
425 | struct extcon_dev *edev = ptr; | ||
426 | |||
427 | if ((val & (1 << obj->cable_index)) != | ||
428 | (edev->state & (1 << obj->cable_index))) { | ||
429 | bool cable_state = true; | ||
430 | |||
431 | obj->previous_value = val; | ||
432 | |||
433 | if (val & (1 << obj->cable_index)) | ||
434 | cable_state = false; | ||
435 | |||
436 | return obj->user_nb->notifier_call(obj->user_nb, | ||
437 | cable_state, ptr); | ||
438 | } | ||
439 | |||
440 | return NOTIFY_OK; | ||
441 | } | ||
442 | |||
443 | /** | ||
444 | * extcon_register_interest() - Register a notifier for a state change of a | ||
445 | * specific cable, not a entier set of cables of a | ||
446 | * extcon device. | ||
447 | * @obj: an empty extcon_specific_cable_nb object to be returned. | ||
448 | * @extcon_name: the name of extcon device. | ||
449 | * @cable_name: the target cable name. | ||
450 | * @nb: the notifier block to get notified. | ||
451 | * | ||
452 | * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets | ||
453 | * the struct for you. | ||
454 | * | ||
455 | * extcon_register_interest is a helper function for those who want to get | ||
456 | * notification for a single specific cable's status change. If a user wants | ||
457 | * to get notification for any changes of all cables of a extcon device, | ||
458 | * he/she should use the general extcon_register_notifier(). | ||
459 | * | ||
460 | * Note that the second parameter given to the callback of nb (val) is | ||
461 | * "old_state", not the current state. The current state can be retrieved | ||
462 | * by looking at the third pameter (edev pointer)'s state value. | ||
463 | */ | ||
464 | int extcon_register_interest(struct extcon_specific_cable_nb *obj, | ||
465 | const char *extcon_name, const char *cable_name, | ||
466 | struct notifier_block *nb) | ||
467 | { | ||
468 | if (!obj || !extcon_name || !cable_name || !nb) | ||
469 | return -EINVAL; | ||
470 | |||
471 | obj->edev = extcon_get_extcon_dev(extcon_name); | ||
472 | if (!obj->edev) | ||
473 | return -ENODEV; | ||
474 | |||
475 | obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); | ||
476 | if (obj->cable_index < 0) | ||
477 | return -ENODEV; | ||
478 | |||
479 | obj->user_nb = nb; | ||
480 | |||
481 | obj->internal_nb.notifier_call = _call_per_cable; | ||
482 | |||
483 | return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * extcon_unregister_interest() - Unregister the notifier registered by | ||
488 | * extcon_register_interest(). | ||
489 | * @obj: the extcon_specific_cable_nb object returned by | ||
490 | * extcon_register_interest(). | ||
491 | */ | ||
492 | int extcon_unregister_interest(struct extcon_specific_cable_nb *obj) | ||
493 | { | ||
494 | if (!obj) | ||
495 | return -EINVAL; | ||
496 | |||
497 | return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb); | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * extcon_register_notifier() - Register a notifee to get notified by | ||
502 | * any attach status changes from the extcon. | ||
503 | * @edev: the extcon device. | ||
504 | * @nb: a notifier block to be registered. | ||
505 | * | ||
506 | * Note that the second parameter given to the callback of nb (val) is | ||
507 | * "old_state", not the current state. The current state can be retrieved | ||
508 | * by looking at the third pameter (edev pointer)'s state value. | ||
509 | */ | ||
510 | int extcon_register_notifier(struct extcon_dev *edev, | ||
511 | struct notifier_block *nb) | ||
512 | { | ||
513 | return raw_notifier_chain_register(&edev->nh, nb); | ||
514 | } | ||
515 | EXPORT_SYMBOL_GPL(extcon_register_notifier); | ||
516 | |||
517 | /** | ||
518 | * extcon_unregister_notifier() - Unregister a notifee from the extcon device. | ||
519 | * @edev: the extcon device. | ||
520 | * @nb: a registered notifier block to be unregistered. | ||
521 | */ | ||
522 | int extcon_unregister_notifier(struct extcon_dev *edev, | ||
523 | struct notifier_block *nb) | ||
524 | { | ||
525 | return raw_notifier_chain_unregister(&edev->nh, nb); | ||
526 | } | ||
527 | EXPORT_SYMBOL_GPL(extcon_unregister_notifier); | ||
528 | |||
529 | static struct device_attribute extcon_attrs[] = { | ||
530 | __ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store), | ||
531 | __ATTR_RO(name), | ||
532 | __ATTR_NULL, | ||
533 | }; | ||
534 | |||
535 | static int create_extcon_class(void) | ||
536 | { | ||
537 | if (!extcon_class) { | ||
538 | extcon_class = class_create(THIS_MODULE, "extcon"); | ||
539 | if (IS_ERR(extcon_class)) | ||
540 | return PTR_ERR(extcon_class); | ||
541 | extcon_class->dev_attrs = extcon_attrs; | ||
542 | |||
543 | #if defined(CONFIG_ANDROID) | ||
544 | switch_class = class_compat_register("switch"); | ||
545 | if (WARN(!switch_class, "cannot allocate")) | ||
546 | return -ENOMEM; | ||
547 | #endif /* CONFIG_ANDROID */ | ||
548 | } | ||
549 | |||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | static void extcon_cleanup(struct extcon_dev *edev, bool skip) | ||
554 | { | ||
555 | mutex_lock(&extcon_dev_list_lock); | ||
556 | list_del(&edev->entry); | ||
557 | mutex_unlock(&extcon_dev_list_lock); | ||
558 | |||
559 | if (!skip && get_device(edev->dev)) { | ||
560 | int index; | ||
561 | |||
562 | if (edev->mutually_exclusive && edev->max_supported) { | ||
563 | for (index = 0; edev->mutually_exclusive[index]; | ||
564 | index++) | ||
565 | kfree(edev->d_attrs_muex[index].attr.name); | ||
566 | kfree(edev->d_attrs_muex); | ||
567 | kfree(edev->attrs_muex); | ||
568 | } | ||
569 | |||
570 | for (index = 0; index < edev->max_supported; index++) | ||
571 | kfree(edev->cables[index].attr_g.name); | ||
572 | |||
573 | if (edev->max_supported) { | ||
574 | kfree(edev->extcon_dev_type.groups); | ||
575 | kfree(edev->cables); | ||
576 | } | ||
577 | |||
578 | device_unregister(edev->dev); | ||
579 | put_device(edev->dev); | ||
580 | } | ||
581 | |||
582 | kfree(edev->dev); | ||
583 | } | ||
584 | |||
585 | static void extcon_dev_release(struct device *dev) | ||
586 | { | ||
587 | struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); | ||
588 | |||
589 | extcon_cleanup(edev, true); | ||
590 | } | ||
591 | |||
592 | static const char *muex_name = "mutually_exclusive"; | ||
593 | static void dummy_sysfs_dev_release(struct device *dev) | ||
594 | { | ||
595 | } | ||
596 | |||
597 | /** | ||
598 | * extcon_dev_register() - Register a new extcon device | ||
599 | * @edev : the new extcon device (should be allocated before calling) | ||
600 | * @dev : the parent device for this extcon device. | ||
601 | * | ||
602 | * Among the members of edev struct, please set the "user initializing data" | ||
603 | * in any case and set the "optional callbacks" if required. However, please | ||
604 | * do not set the values of "internal data", which are initialized by | ||
605 | * this function. | ||
606 | */ | ||
607 | int extcon_dev_register(struct extcon_dev *edev, struct device *dev) | ||
608 | { | ||
609 | int ret, index = 0; | ||
610 | |||
611 | if (!extcon_class) { | ||
612 | ret = create_extcon_class(); | ||
613 | if (ret < 0) | ||
614 | return ret; | ||
615 | } | ||
616 | |||
617 | if (edev->supported_cable) { | ||
618 | /* Get size of array */ | ||
619 | for (index = 0; edev->supported_cable[index]; index++) | ||
620 | ; | ||
621 | edev->max_supported = index; | ||
622 | } else { | ||
623 | edev->max_supported = 0; | ||
624 | } | ||
625 | |||
626 | if (index > SUPPORTED_CABLE_MAX) { | ||
627 | dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n"); | ||
628 | return -EINVAL; | ||
629 | } | ||
630 | |||
631 | edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL); | ||
632 | if (!edev->dev) | ||
633 | return -ENOMEM; | ||
634 | edev->dev->parent = dev; | ||
635 | edev->dev->class = extcon_class; | ||
636 | edev->dev->release = extcon_dev_release; | ||
637 | |||
638 | dev_set_name(edev->dev, edev->name ? edev->name : dev_name(dev)); | ||
639 | |||
640 | if (edev->max_supported) { | ||
641 | char buf[10]; | ||
642 | char *str; | ||
643 | struct extcon_cable *cable; | ||
644 | |||
645 | edev->cables = kzalloc(sizeof(struct extcon_cable) * | ||
646 | edev->max_supported, GFP_KERNEL); | ||
647 | if (!edev->cables) { | ||
648 | ret = -ENOMEM; | ||
649 | goto err_sysfs_alloc; | ||
650 | } | ||
651 | for (index = 0; index < edev->max_supported; index++) { | ||
652 | cable = &edev->cables[index]; | ||
653 | |||
654 | snprintf(buf, 10, "cable.%d", index); | ||
655 | str = kzalloc(sizeof(char) * (strlen(buf) + 1), | ||
656 | GFP_KERNEL); | ||
657 | if (!str) { | ||
658 | for (index--; index >= 0; index--) { | ||
659 | cable = &edev->cables[index]; | ||
660 | kfree(cable->attr_g.name); | ||
661 | } | ||
662 | ret = -ENOMEM; | ||
663 | |||
664 | goto err_alloc_cables; | ||
665 | } | ||
666 | strcpy(str, buf); | ||
667 | |||
668 | cable->edev = edev; | ||
669 | cable->cable_index = index; | ||
670 | cable->attrs[0] = &cable->attr_name.attr; | ||
671 | cable->attrs[1] = &cable->attr_state.attr; | ||
672 | cable->attrs[2] = NULL; | ||
673 | cable->attr_g.name = str; | ||
674 | cable->attr_g.attrs = cable->attrs; | ||
675 | |||
676 | cable->attr_name.attr.name = "name"; | ||
677 | cable->attr_name.attr.mode = 0444; | ||
678 | cable->attr_name.show = cable_name_show; | ||
679 | |||
680 | cable->attr_state.attr.name = "state"; | ||
681 | cable->attr_state.attr.mode = 0644; | ||
682 | cable->attr_state.show = cable_state_show; | ||
683 | cable->attr_state.store = cable_state_store; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | if (edev->max_supported && edev->mutually_exclusive) { | ||
688 | char buf[80]; | ||
689 | char *name; | ||
690 | |||
691 | /* Count the size of mutually_exclusive array */ | ||
692 | for (index = 0; edev->mutually_exclusive[index]; index++) | ||
693 | ; | ||
694 | |||
695 | edev->attrs_muex = kzalloc(sizeof(struct attribute *) * | ||
696 | (index + 1), GFP_KERNEL); | ||
697 | if (!edev->attrs_muex) { | ||
698 | ret = -ENOMEM; | ||
699 | goto err_muex; | ||
700 | } | ||
701 | |||
702 | edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) * | ||
703 | index, GFP_KERNEL); | ||
704 | if (!edev->d_attrs_muex) { | ||
705 | ret = -ENOMEM; | ||
706 | kfree(edev->attrs_muex); | ||
707 | goto err_muex; | ||
708 | } | ||
709 | |||
710 | for (index = 0; edev->mutually_exclusive[index]; index++) { | ||
711 | sprintf(buf, "0x%x", edev->mutually_exclusive[index]); | ||
712 | name = kzalloc(sizeof(char) * (strlen(buf) + 1), | ||
713 | GFP_KERNEL); | ||
714 | if (!name) { | ||
715 | for (index--; index >= 0; index--) { | ||
716 | kfree(edev->d_attrs_muex[index].attr. | ||
717 | name); | ||
718 | } | ||
719 | kfree(edev->d_attrs_muex); | ||
720 | kfree(edev->attrs_muex); | ||
721 | ret = -ENOMEM; | ||
722 | goto err_muex; | ||
723 | } | ||
724 | strcpy(name, buf); | ||
725 | edev->d_attrs_muex[index].attr.name = name; | ||
726 | edev->d_attrs_muex[index].attr.mode = 0000; | ||
727 | edev->attrs_muex[index] = &edev->d_attrs_muex[index] | ||
728 | .attr; | ||
729 | } | ||
730 | edev->attr_g_muex.name = muex_name; | ||
731 | edev->attr_g_muex.attrs = edev->attrs_muex; | ||
732 | |||
733 | } | ||
734 | |||
735 | if (edev->max_supported) { | ||
736 | edev->extcon_dev_type.groups = | ||
737 | kzalloc(sizeof(struct attribute_group *) * | ||
738 | (edev->max_supported + 2), GFP_KERNEL); | ||
739 | if (!edev->extcon_dev_type.groups) { | ||
740 | ret = -ENOMEM; | ||
741 | goto err_alloc_groups; | ||
742 | } | ||
743 | |||
744 | edev->extcon_dev_type.name = dev_name(edev->dev); | ||
745 | edev->extcon_dev_type.release = dummy_sysfs_dev_release; | ||
746 | |||
747 | for (index = 0; index < edev->max_supported; index++) | ||
748 | edev->extcon_dev_type.groups[index] = | ||
749 | &edev->cables[index].attr_g; | ||
750 | if (edev->mutually_exclusive) | ||
751 | edev->extcon_dev_type.groups[index] = | ||
752 | &edev->attr_g_muex; | ||
753 | |||
754 | edev->dev->type = &edev->extcon_dev_type; | ||
755 | } | ||
756 | |||
757 | ret = device_register(edev->dev); | ||
758 | if (ret) { | ||
759 | put_device(edev->dev); | ||
760 | goto err_dev; | ||
761 | } | ||
762 | #if defined(CONFIG_ANDROID) | ||
763 | if (switch_class) | ||
764 | ret = class_compat_create_link(switch_class, edev->dev, | ||
765 | dev); | ||
766 | #endif /* CONFIG_ANDROID */ | ||
767 | |||
768 | spin_lock_init(&edev->lock); | ||
769 | |||
770 | RAW_INIT_NOTIFIER_HEAD(&edev->nh); | ||
771 | |||
772 | dev_set_drvdata(edev->dev, edev); | ||
773 | edev->state = 0; | ||
774 | |||
775 | mutex_lock(&extcon_dev_list_lock); | ||
776 | list_add(&edev->entry, &extcon_dev_list); | ||
777 | mutex_unlock(&extcon_dev_list_lock); | ||
778 | |||
779 | return 0; | ||
780 | |||
781 | err_dev: | ||
782 | if (edev->max_supported) | ||
783 | kfree(edev->extcon_dev_type.groups); | ||
784 | err_alloc_groups: | ||
785 | if (edev->max_supported && edev->mutually_exclusive) { | ||
786 | for (index = 0; edev->mutually_exclusive[index]; index++) | ||
787 | kfree(edev->d_attrs_muex[index].attr.name); | ||
788 | kfree(edev->d_attrs_muex); | ||
789 | kfree(edev->attrs_muex); | ||
790 | } | ||
791 | err_muex: | ||
792 | for (index = 0; index < edev->max_supported; index++) | ||
793 | kfree(edev->cables[index].attr_g.name); | ||
794 | err_alloc_cables: | ||
795 | if (edev->max_supported) | ||
796 | kfree(edev->cables); | ||
797 | err_sysfs_alloc: | ||
798 | kfree(edev->dev); | ||
799 | return ret; | ||
800 | } | ||
801 | EXPORT_SYMBOL_GPL(extcon_dev_register); | ||
802 | |||
803 | /** | ||
804 | * extcon_dev_unregister() - Unregister the extcon device. | ||
805 | * @edev: the extcon device instance to be unregitered. | ||
806 | * | ||
807 | * Note that this does not call kfree(edev) because edev was not allocated | ||
808 | * by this class. | ||
809 | */ | ||
810 | void extcon_dev_unregister(struct extcon_dev *edev) | ||
811 | { | ||
812 | extcon_cleanup(edev, false); | ||
813 | } | ||
814 | EXPORT_SYMBOL_GPL(extcon_dev_unregister); | ||
815 | |||
816 | static int __init extcon_class_init(void) | ||
817 | { | ||
818 | return create_extcon_class(); | ||
819 | } | ||
820 | module_init(extcon_class_init); | ||
821 | |||
822 | static void __exit extcon_class_exit(void) | ||
823 | { | ||
824 | class_destroy(extcon_class); | ||
825 | } | ||
826 | module_exit(extcon_class_exit); | ||
827 | |||
828 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
829 | MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); | ||
830 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
831 | MODULE_DESCRIPTION("External connector (extcon) class driver"); | ||
832 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c new file mode 100644 index 000000000000..fe7a07b47336 --- /dev/null +++ b/drivers/extcon/extcon_gpio.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * drivers/extcon/extcon_gpio.c | ||
3 | * | ||
4 | * Single-state GPIO extcon driver based on extcon class | ||
5 | * | ||
6 | * Copyright (C) 2008 Google, Inc. | ||
7 | * Author: Mike Lockwood <lockwood@android.com> | ||
8 | * | ||
9 | * Modified by MyungJoo Ham <myungjoo.ham@samsung.com> to support extcon | ||
10 | * (originally switch class is supported) | ||
11 | * | ||
12 | * This software is licensed under the terms of the GNU General Public | ||
13 | * License version 2, as published by the Free Software Foundation, and | ||
14 | * may be copied, distributed, and modified under those terms. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/extcon.h> | ||
30 | #include <linux/workqueue.h> | ||
31 | #include <linux/gpio.h> | ||
32 | #include <linux/extcon.h> | ||
33 | #include <linux/extcon/extcon_gpio.h> | ||
34 | |||
35 | struct gpio_extcon_data { | ||
36 | struct extcon_dev edev; | ||
37 | unsigned gpio; | ||
38 | const char *state_on; | ||
39 | const char *state_off; | ||
40 | int irq; | ||
41 | struct delayed_work work; | ||
42 | unsigned long debounce_jiffies; | ||
43 | }; | ||
44 | |||
45 | static void gpio_extcon_work(struct work_struct *work) | ||
46 | { | ||
47 | int state; | ||
48 | struct gpio_extcon_data *data = | ||
49 | container_of(to_delayed_work(work), struct gpio_extcon_data, | ||
50 | work); | ||
51 | |||
52 | state = gpio_get_value(data->gpio); | ||
53 | extcon_set_state(&data->edev, state); | ||
54 | } | ||
55 | |||
56 | static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | ||
57 | { | ||
58 | struct gpio_extcon_data *extcon_data = dev_id; | ||
59 | |||
60 | schedule_delayed_work(&extcon_data->work, | ||
61 | extcon_data->debounce_jiffies); | ||
62 | return IRQ_HANDLED; | ||
63 | } | ||
64 | |||
65 | static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf) | ||
66 | { | ||
67 | struct gpio_extcon_data *extcon_data = | ||
68 | container_of(edev, struct gpio_extcon_data, edev); | ||
69 | const char *state; | ||
70 | if (extcon_get_state(edev)) | ||
71 | state = extcon_data->state_on; | ||
72 | else | ||
73 | state = extcon_data->state_off; | ||
74 | |||
75 | if (state) | ||
76 | return sprintf(buf, "%s\n", state); | ||
77 | return -EINVAL; | ||
78 | } | ||
79 | |||
80 | static int __devinit gpio_extcon_probe(struct platform_device *pdev) | ||
81 | { | ||
82 | struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data; | ||
83 | struct gpio_extcon_data *extcon_data; | ||
84 | int ret = 0; | ||
85 | |||
86 | if (!pdata) | ||
87 | return -EBUSY; | ||
88 | if (!pdata->irq_flags) { | ||
89 | dev_err(&pdev->dev, "IRQ flag is not specified.\n"); | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data), | ||
94 | GFP_KERNEL); | ||
95 | if (!extcon_data) | ||
96 | return -ENOMEM; | ||
97 | |||
98 | extcon_data->edev.name = pdata->name; | ||
99 | extcon_data->gpio = pdata->gpio; | ||
100 | extcon_data->state_on = pdata->state_on; | ||
101 | extcon_data->state_off = pdata->state_off; | ||
102 | if (pdata->state_on && pdata->state_off) | ||
103 | extcon_data->edev.print_state = extcon_gpio_print_state; | ||
104 | extcon_data->debounce_jiffies = msecs_to_jiffies(pdata->debounce); | ||
105 | |||
106 | ret = extcon_dev_register(&extcon_data->edev, &pdev->dev); | ||
107 | if (ret < 0) | ||
108 | goto err_extcon_dev_register; | ||
109 | |||
110 | ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); | ||
111 | if (ret < 0) | ||
112 | goto err_request_gpio; | ||
113 | |||
114 | INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work); | ||
115 | |||
116 | extcon_data->irq = gpio_to_irq(extcon_data->gpio); | ||
117 | if (extcon_data->irq < 0) { | ||
118 | ret = extcon_data->irq; | ||
119 | goto err_detect_irq_num_failed; | ||
120 | } | ||
121 | |||
122 | ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler, | ||
123 | pdata->irq_flags, pdev->name, | ||
124 | extcon_data); | ||
125 | if (ret < 0) | ||
126 | goto err_request_irq; | ||
127 | |||
128 | /* Perform initial detection */ | ||
129 | gpio_extcon_work(&extcon_data->work.work); | ||
130 | |||
131 | return 0; | ||
132 | |||
133 | err_request_irq: | ||
134 | err_detect_irq_num_failed: | ||
135 | gpio_free(extcon_data->gpio); | ||
136 | err_request_gpio: | ||
137 | extcon_dev_unregister(&extcon_data->edev); | ||
138 | err_extcon_dev_register: | ||
139 | devm_kfree(&pdev->dev, extcon_data); | ||
140 | |||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | static int __devexit gpio_extcon_remove(struct platform_device *pdev) | ||
145 | { | ||
146 | struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev); | ||
147 | |||
148 | cancel_delayed_work_sync(&extcon_data->work); | ||
149 | gpio_free(extcon_data->gpio); | ||
150 | extcon_dev_unregister(&extcon_data->edev); | ||
151 | devm_kfree(&pdev->dev, extcon_data); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static struct platform_driver gpio_extcon_driver = { | ||
157 | .probe = gpio_extcon_probe, | ||
158 | .remove = __devexit_p(gpio_extcon_remove), | ||
159 | .driver = { | ||
160 | .name = "extcon-gpio", | ||
161 | .owner = THIS_MODULE, | ||
162 | }, | ||
163 | }; | ||
164 | |||
165 | module_platform_driver(gpio_extcon_driver); | ||
166 | |||
167 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
168 | MODULE_DESCRIPTION("GPIO extcon driver"); | ||
169 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 3dd29399cef5..8950f6261bbb 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c | |||
@@ -83,8 +83,7 @@ EXPORT_SYMBOL(devm_gpio_request); | |||
83 | void devm_gpio_free(struct device *dev, unsigned int gpio) | 83 | void devm_gpio_free(struct device *dev, unsigned int gpio) |
84 | { | 84 | { |
85 | 85 | ||
86 | WARN_ON(devres_destroy(dev, devm_gpio_release, devm_gpio_match, | 86 | WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match, |
87 | &gpio)); | 87 | &gpio)); |
88 | gpio_free(gpio); | ||
89 | } | 88 | } |
90 | EXPORT_SYMBOL(devm_gpio_free); | 89 | EXPORT_SYMBOL(devm_gpio_free); |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 9ffbfc575a0c..2b8b8d4558d2 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -46,40 +46,61 @@ struct vmbus_channel_message_table_entry { | |||
46 | * | 46 | * |
47 | * @icmsghdrp is of type &struct icmsg_hdr. | 47 | * @icmsghdrp is of type &struct icmsg_hdr. |
48 | * @negop is of type &struct icmsg_negotiate. | 48 | * @negop is of type &struct icmsg_negotiate. |
49 | * Set up and fill in default negotiate response message. This response can | 49 | * Set up and fill in default negotiate response message. |
50 | * come from both the vmbus driver and the hv_utils driver. The current api | 50 | * |
51 | * will respond properly to both Windows 2008 and Windows 2008-R2 operating | 51 | * The max_fw_version specifies the maximum framework version that |
52 | * systems. | 52 | * we can support and max _srv_version specifies the maximum service |
53 | * version we can support. A special value MAX_SRV_VER can be | ||
54 | * specified to indicate that we can handle the maximum version | ||
55 | * exposed by the host. | ||
53 | * | 56 | * |
54 | * Mainly used by Hyper-V drivers. | 57 | * Mainly used by Hyper-V drivers. |
55 | */ | 58 | */ |
56 | void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, | 59 | void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, |
57 | struct icmsg_negotiate *negop, u8 *buf) | 60 | struct icmsg_negotiate *negop, u8 *buf, |
61 | int max_fw_version, int max_srv_version) | ||
58 | { | 62 | { |
59 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 63 | int icframe_vercnt; |
60 | icmsghdrp->icmsgsize = 0x10; | 64 | int icmsg_vercnt; |
61 | 65 | int i; | |
62 | negop = (struct icmsg_negotiate *)&buf[ | 66 | |
63 | sizeof(struct vmbuspipe_hdr) + | 67 | icmsghdrp->icmsgsize = 0x10; |
64 | sizeof(struct icmsg_hdr)]; | 68 | |
65 | 69 | negop = (struct icmsg_negotiate *)&buf[ | |
66 | if (negop->icframe_vercnt == 2 && | 70 | sizeof(struct vmbuspipe_hdr) + |
67 | negop->icversion_data[1].major == 3) { | 71 | sizeof(struct icmsg_hdr)]; |
68 | negop->icversion_data[0].major = 3; | 72 | |
69 | negop->icversion_data[0].minor = 0; | 73 | icframe_vercnt = negop->icframe_vercnt; |
70 | negop->icversion_data[1].major = 3; | 74 | icmsg_vercnt = negop->icmsg_vercnt; |
71 | negop->icversion_data[1].minor = 0; | 75 | |
72 | } else { | 76 | /* |
73 | negop->icversion_data[0].major = 1; | 77 | * Select the framework version number we will |
74 | negop->icversion_data[0].minor = 0; | 78 | * support. |
75 | negop->icversion_data[1].major = 1; | 79 | */ |
76 | negop->icversion_data[1].minor = 0; | 80 | |
77 | } | 81 | for (i = 0; i < negop->icframe_vercnt; i++) { |
82 | if (negop->icversion_data[i].major <= max_fw_version) | ||
83 | icframe_vercnt = negop->icversion_data[i].major; | ||
84 | } | ||
78 | 85 | ||
79 | negop->icframe_vercnt = 1; | 86 | for (i = negop->icframe_vercnt; |
80 | negop->icmsg_vercnt = 1; | 87 | (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { |
88 | if (negop->icversion_data[i].major <= max_srv_version) | ||
89 | icmsg_vercnt = negop->icversion_data[i].major; | ||
81 | } | 90 | } |
91 | |||
92 | /* | ||
93 | * Respond with the maximum framework and service | ||
94 | * version numbers we can support. | ||
95 | */ | ||
96 | negop->icframe_vercnt = 1; | ||
97 | negop->icmsg_vercnt = 1; | ||
98 | negop->icversion_data[0].major = icframe_vercnt; | ||
99 | negop->icversion_data[0].minor = 0; | ||
100 | negop->icversion_data[1].major = icmsg_vercnt; | ||
101 | negop->icversion_data[1].minor = 0; | ||
82 | } | 102 | } |
103 | |||
83 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); | 104 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); |
84 | 105 | ||
85 | /* | 106 | /* |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 15956bd48b48..86f8885aeb45 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -252,7 +252,7 @@ void hv_cleanup(void) | |||
252 | * | 252 | * |
253 | * This involves a hypercall. | 253 | * This involves a hypercall. |
254 | */ | 254 | */ |
255 | u16 hv_post_message(union hv_connection_id connection_id, | 255 | int hv_post_message(union hv_connection_id connection_id, |
256 | enum hv_message_type message_type, | 256 | enum hv_message_type message_type, |
257 | void *payload, size_t payload_size) | 257 | void *payload, size_t payload_size) |
258 | { | 258 | { |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 6186025209ce..0012eed6d872 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
@@ -394,7 +394,8 @@ void hv_kvp_onchannelcallback(void *context) | |||
394 | sizeof(struct vmbuspipe_hdr)]; | 394 | sizeof(struct vmbuspipe_hdr)]; |
395 | 395 | ||
396 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 396 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
397 | vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer); | 397 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
398 | recv_buffer, MAX_SRV_VER, MAX_SRV_VER); | ||
398 | } else { | 399 | } else { |
399 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ | 400 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ |
400 | sizeof(struct vmbuspipe_hdr) + | 401 | sizeof(struct vmbuspipe_hdr) + |
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index dbb8b8eec210..d3ac6a40118b 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c | |||
@@ -70,7 +70,8 @@ static void shutdown_onchannelcallback(void *context) | |||
70 | sizeof(struct vmbuspipe_hdr)]; | 70 | sizeof(struct vmbuspipe_hdr)]; |
71 | 71 | ||
72 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 72 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
73 | vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); | 73 | vmbus_prep_negotiate_resp(icmsghdrp, negop, |
74 | shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | ||
74 | } else { | 75 | } else { |
75 | shutdown_msg = | 76 | shutdown_msg = |
76 | (struct shutdown_msg_data *)&shut_txf_buf[ | 77 | (struct shutdown_msg_data *)&shut_txf_buf[ |
@@ -195,7 +196,8 @@ static void timesync_onchannelcallback(void *context) | |||
195 | sizeof(struct vmbuspipe_hdr)]; | 196 | sizeof(struct vmbuspipe_hdr)]; |
196 | 197 | ||
197 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 198 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
198 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); | 199 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, |
200 | MAX_SRV_VER, MAX_SRV_VER); | ||
199 | } else { | 201 | } else { |
200 | timedatap = (struct ictimesync_data *)&time_txf_buf[ | 202 | timedatap = (struct ictimesync_data *)&time_txf_buf[ |
201 | sizeof(struct vmbuspipe_hdr) + | 203 | sizeof(struct vmbuspipe_hdr) + |
@@ -234,7 +236,8 @@ static void heartbeat_onchannelcallback(void *context) | |||
234 | sizeof(struct vmbuspipe_hdr)]; | 236 | sizeof(struct vmbuspipe_hdr)]; |
235 | 237 | ||
236 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 238 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
237 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); | 239 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, |
240 | hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); | ||
238 | } else { | 241 | } else { |
239 | heartbeat_msg = | 242 | heartbeat_msg = |
240 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ | 243 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 699f0d8e59ed..b9426a6592ee 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -495,7 +495,7 @@ extern int hv_init(void); | |||
495 | 495 | ||
496 | extern void hv_cleanup(void); | 496 | extern void hv_cleanup(void); |
497 | 497 | ||
498 | extern u16 hv_post_message(union hv_connection_id connection_id, | 498 | extern int hv_post_message(union hv_connection_id connection_id, |
499 | enum hv_message_type message_type, | 499 | enum hv_message_type message_type, |
500 | void *payload, size_t payload_size); | 500 | void *payload, size_t payload_size); |
501 | 501 | ||
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig new file mode 100644 index 000000000000..067f31174a0e --- /dev/null +++ b/drivers/memory/Kconfig | |||
@@ -0,0 +1,43 @@ | |||
1 | # | ||
2 | # Memory devices | ||
3 | # | ||
4 | |||
5 | menuconfig MEMORY | ||
6 | bool "Memory Controller drivers" | ||
7 | |||
8 | if MEMORY | ||
9 | |||
10 | config TI_EMIF | ||
11 | tristate "Texas Instruments EMIF driver" | ||
12 | depends on ARCH_OMAP2PLUS | ||
13 | select DDR | ||
14 | help | ||
15 | This driver is for the EMIF module available in Texas Instruments | ||
16 | SoCs. EMIF is an SDRAM controller that, based on its revision, | ||
17 | supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. | ||
18 | This driver takes care of only LPDDR2 memories presently. The | ||
19 | functions of the driver includes re-configuring AC timing | ||
20 | parameters and other settings during frequency, voltage and | ||
21 | temperature changes | ||
22 | |||
23 | config TEGRA20_MC | ||
24 | bool "Tegra20 Memory Controller(MC) driver" | ||
25 | default y | ||
26 | depends on ARCH_TEGRA_2x_SOC | ||
27 | help | ||
28 | This driver is for the Memory Controller(MC) module available | ||
29 | in Tegra20 SoCs, mainly for a address translation fault | ||
30 | analysis, especially for IOMMU/GART(Graphics Address | ||
31 | Relocation Table) module. | ||
32 | |||
33 | config TEGRA30_MC | ||
34 | bool "Tegra30 Memory Controller(MC) driver" | ||
35 | default y | ||
36 | depends on ARCH_TEGRA_3x_SOC | ||
37 | help | ||
38 | This driver is for the Memory Controller(MC) module available | ||
39 | in Tegra30 SoCs, mainly for a address translation fault | ||
40 | analysis, especially for IOMMU/SMMU(System Memory Management | ||
41 | Unit) module. | ||
42 | |||
43 | endif | ||
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile new file mode 100644 index 000000000000..42b3ce9d80fc --- /dev/null +++ b/drivers/memory/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for memory devices | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_TI_EMIF) += emif.o | ||
6 | obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o | ||
7 | obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o | ||
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c new file mode 100644 index 000000000000..33a4396b24cb --- /dev/null +++ b/drivers/memory/emif.c | |||
@@ -0,0 +1,1670 @@ | |||
1 | /* | ||
2 | * EMIF driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Aneesh V <aneesh@ti.com> | ||
7 | * Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/reboot.h> | ||
15 | #include <linux/platform_data/emif_plat.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/debugfs.h> | ||
22 | #include <linux/seq_file.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/list.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | #include <memory/jedec_ddr.h> | ||
27 | #include "emif.h" | ||
28 | |||
29 | /** | ||
30 | * struct emif_data - Per device static data for driver's use | ||
31 | * @duplicate: Whether the DDR devices attached to this EMIF | ||
32 | * instance are exactly same as that on EMIF1. In | ||
33 | * this case we can save some memory and processing | ||
34 | * @temperature_level: Maximum temperature of LPDDR2 devices attached | ||
35 | * to this EMIF - read from MR4 register. If there | ||
36 | * are two devices attached to this EMIF, this | ||
37 | * value is the maximum of the two temperature | ||
38 | * levels. | ||
39 | * @node: node in the device list | ||
40 | * @base: base address of memory-mapped IO registers. | ||
41 | * @dev: device pointer. | ||
42 | * @addressing table with addressing information from the spec | ||
43 | * @regs_cache: An array of 'struct emif_regs' that stores | ||
44 | * calculated register values for different | ||
45 | * frequencies, to avoid re-calculating them on | ||
46 | * each DVFS transition. | ||
47 | * @curr_regs: The set of register values used in the last | ||
48 | * frequency change (i.e. corresponding to the | ||
49 | * frequency in effect at the moment) | ||
50 | * @plat_data: Pointer to saved platform data. | ||
51 | * @debugfs_root: dentry to the root folder for EMIF in debugfs | ||
52 | */ | ||
53 | struct emif_data { | ||
54 | u8 duplicate; | ||
55 | u8 temperature_level; | ||
56 | u8 lpmode; | ||
57 | struct list_head node; | ||
58 | unsigned long irq_state; | ||
59 | void __iomem *base; | ||
60 | struct device *dev; | ||
61 | const struct lpddr2_addressing *addressing; | ||
62 | struct emif_regs *regs_cache[EMIF_MAX_NUM_FREQUENCIES]; | ||
63 | struct emif_regs *curr_regs; | ||
64 | struct emif_platform_data *plat_data; | ||
65 | struct dentry *debugfs_root; | ||
66 | }; | ||
67 | |||
68 | static struct emif_data *emif1; | ||
69 | static spinlock_t emif_lock; | ||
70 | static unsigned long irq_state; | ||
71 | static u32 t_ck; /* DDR clock period in ps */ | ||
72 | static LIST_HEAD(device_list); | ||
73 | |||
74 | static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, | ||
75 | struct emif_regs *regs) | ||
76 | { | ||
77 | u32 type = emif->plat_data->device_info->type; | ||
78 | u32 ip_rev = emif->plat_data->ip_rev; | ||
79 | |||
80 | seq_printf(s, "EMIF register cache dump for %dMHz\n", | ||
81 | regs->freq/1000000); | ||
82 | |||
83 | seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw); | ||
84 | seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw); | ||
85 | seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw); | ||
86 | seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw); | ||
87 | |||
88 | if (ip_rev == EMIF_4D) { | ||
89 | seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n", | ||
90 | regs->read_idle_ctrl_shdw_normal); | ||
91 | seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n", | ||
92 | regs->read_idle_ctrl_shdw_volt_ramp); | ||
93 | } else if (ip_rev == EMIF_4D5) { | ||
94 | seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n", | ||
95 | regs->dll_calib_ctrl_shdw_normal); | ||
96 | seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n", | ||
97 | regs->dll_calib_ctrl_shdw_volt_ramp); | ||
98 | } | ||
99 | |||
100 | if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { | ||
101 | seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n", | ||
102 | regs->ref_ctrl_shdw_derated); | ||
103 | seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n", | ||
104 | regs->sdram_tim1_shdw_derated); | ||
105 | seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n", | ||
106 | regs->sdram_tim3_shdw_derated); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static int emif_regdump_show(struct seq_file *s, void *unused) | ||
111 | { | ||
112 | struct emif_data *emif = s->private; | ||
113 | struct emif_regs **regs_cache; | ||
114 | int i; | ||
115 | |||
116 | if (emif->duplicate) | ||
117 | regs_cache = emif1->regs_cache; | ||
118 | else | ||
119 | regs_cache = emif->regs_cache; | ||
120 | |||
121 | for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) { | ||
122 | do_emif_regdump_show(s, emif, regs_cache[i]); | ||
123 | seq_printf(s, "\n"); | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int emif_regdump_open(struct inode *inode, struct file *file) | ||
130 | { | ||
131 | return single_open(file, emif_regdump_show, inode->i_private); | ||
132 | } | ||
133 | |||
134 | static const struct file_operations emif_regdump_fops = { | ||
135 | .open = emif_regdump_open, | ||
136 | .read = seq_read, | ||
137 | .release = single_release, | ||
138 | }; | ||
139 | |||
140 | static int emif_mr4_show(struct seq_file *s, void *unused) | ||
141 | { | ||
142 | struct emif_data *emif = s->private; | ||
143 | |||
144 | seq_printf(s, "MR4=%d\n", emif->temperature_level); | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int emif_mr4_open(struct inode *inode, struct file *file) | ||
149 | { | ||
150 | return single_open(file, emif_mr4_show, inode->i_private); | ||
151 | } | ||
152 | |||
153 | static const struct file_operations emif_mr4_fops = { | ||
154 | .open = emif_mr4_open, | ||
155 | .read = seq_read, | ||
156 | .release = single_release, | ||
157 | }; | ||
158 | |||
159 | static int __init_or_module emif_debugfs_init(struct emif_data *emif) | ||
160 | { | ||
161 | struct dentry *dentry; | ||
162 | int ret; | ||
163 | |||
164 | dentry = debugfs_create_dir(dev_name(emif->dev), NULL); | ||
165 | if (IS_ERR(dentry)) { | ||
166 | ret = PTR_ERR(dentry); | ||
167 | goto err0; | ||
168 | } | ||
169 | emif->debugfs_root = dentry; | ||
170 | |||
171 | dentry = debugfs_create_file("regcache_dump", S_IRUGO, | ||
172 | emif->debugfs_root, emif, &emif_regdump_fops); | ||
173 | if (IS_ERR(dentry)) { | ||
174 | ret = PTR_ERR(dentry); | ||
175 | goto err1; | ||
176 | } | ||
177 | |||
178 | dentry = debugfs_create_file("mr4", S_IRUGO, | ||
179 | emif->debugfs_root, emif, &emif_mr4_fops); | ||
180 | if (IS_ERR(dentry)) { | ||
181 | ret = PTR_ERR(dentry); | ||
182 | goto err1; | ||
183 | } | ||
184 | |||
185 | return 0; | ||
186 | err1: | ||
187 | debugfs_remove_recursive(emif->debugfs_root); | ||
188 | err0: | ||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static void __exit emif_debugfs_exit(struct emif_data *emif) | ||
193 | { | ||
194 | debugfs_remove_recursive(emif->debugfs_root); | ||
195 | emif->debugfs_root = NULL; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * Calculate the period of DDR clock from frequency value | ||
200 | */ | ||
201 | static void set_ddr_clk_period(u32 freq) | ||
202 | { | ||
203 | /* Divide 10^12 by frequency to get period in ps */ | ||
204 | t_ck = (u32)DIV_ROUND_UP_ULL(1000000000000ull, freq); | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Get bus width used by EMIF. Note that this may be different from the | ||
209 | * bus width of the DDR devices used. For instance two 16-bit DDR devices | ||
210 | * may be connected to a given CS of EMIF. In this case bus width as far | ||
211 | * as EMIF is concerned is 32, where as the DDR bus width is 16 bits. | ||
212 | */ | ||
213 | static u32 get_emif_bus_width(struct emif_data *emif) | ||
214 | { | ||
215 | u32 width; | ||
216 | void __iomem *base = emif->base; | ||
217 | |||
218 | width = (readl(base + EMIF_SDRAM_CONFIG) & NARROW_MODE_MASK) | ||
219 | >> NARROW_MODE_SHIFT; | ||
220 | width = width == 0 ? 32 : 16; | ||
221 | |||
222 | return width; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * Get the CL from SDRAM_CONFIG register | ||
227 | */ | ||
228 | static u32 get_cl(struct emif_data *emif) | ||
229 | { | ||
230 | u32 cl; | ||
231 | void __iomem *base = emif->base; | ||
232 | |||
233 | cl = (readl(base + EMIF_SDRAM_CONFIG) & CL_MASK) >> CL_SHIFT; | ||
234 | |||
235 | return cl; | ||
236 | } | ||
237 | |||
238 | static void set_lpmode(struct emif_data *emif, u8 lpmode) | ||
239 | { | ||
240 | u32 temp; | ||
241 | void __iomem *base = emif->base; | ||
242 | |||
243 | temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); | ||
244 | temp &= ~LP_MODE_MASK; | ||
245 | temp |= (lpmode << LP_MODE_SHIFT); | ||
246 | writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL); | ||
247 | } | ||
248 | |||
249 | static void do_freq_update(void) | ||
250 | { | ||
251 | struct emif_data *emif; | ||
252 | |||
253 | /* | ||
254 | * Workaround for errata i728: Disable LPMODE during FREQ_UPDATE | ||
255 | * | ||
256 | * i728 DESCRIPTION: | ||
257 | * The EMIF automatically puts the SDRAM into self-refresh mode | ||
258 | * after the EMIF has not performed accesses during | ||
259 | * EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles | ||
260 | * and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set | ||
261 | * to 0x2. If during a small window the following three events | ||
262 | * occur: | ||
263 | * - The SR_TIMING counter expires | ||
264 | * - And frequency change is requested | ||
265 | * - And OCP access is requested | ||
266 | * Then it causes instable clock on the DDR interface. | ||
267 | * | ||
268 | * WORKAROUND | ||
269 | * To avoid the occurrence of the three events, the workaround | ||
270 | * is to disable the self-refresh when requesting a frequency | ||
271 | * change. Before requesting a frequency change the software must | ||
272 | * program EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0. When the | ||
273 | * frequency change has been done, the software can reprogram | ||
274 | * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2 | ||
275 | */ | ||
276 | list_for_each_entry(emif, &device_list, node) { | ||
277 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
278 | set_lpmode(emif, EMIF_LP_MODE_DISABLE); | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * TODO: Do FREQ_UPDATE here when an API | ||
283 | * is available for this as part of the new | ||
284 | * clock framework | ||
285 | */ | ||
286 | |||
287 | list_for_each_entry(emif, &device_list, node) { | ||
288 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
289 | set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /* Find addressing table entry based on the device's type and density */ | ||
294 | static const struct lpddr2_addressing *get_addressing_table( | ||
295 | const struct ddr_device_info *device_info) | ||
296 | { | ||
297 | u32 index, type, density; | ||
298 | |||
299 | type = device_info->type; | ||
300 | density = device_info->density; | ||
301 | |||
302 | switch (type) { | ||
303 | case DDR_TYPE_LPDDR2_S4: | ||
304 | index = density - 1; | ||
305 | break; | ||
306 | case DDR_TYPE_LPDDR2_S2: | ||
307 | switch (density) { | ||
308 | case DDR_DENSITY_1Gb: | ||
309 | case DDR_DENSITY_2Gb: | ||
310 | index = density + 3; | ||
311 | break; | ||
312 | default: | ||
313 | index = density - 1; | ||
314 | } | ||
315 | break; | ||
316 | default: | ||
317 | return NULL; | ||
318 | } | ||
319 | |||
320 | return &lpddr2_jedec_addressing_table[index]; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * Find the the right timing table from the array of timing | ||
325 | * tables of the device using DDR clock frequency | ||
326 | */ | ||
327 | static const struct lpddr2_timings *get_timings_table(struct emif_data *emif, | ||
328 | u32 freq) | ||
329 | { | ||
330 | u32 i, min, max, freq_nearest; | ||
331 | const struct lpddr2_timings *timings = NULL; | ||
332 | const struct lpddr2_timings *timings_arr = emif->plat_data->timings; | ||
333 | struct device *dev = emif->dev; | ||
334 | |||
335 | /* Start with a very high frequency - 1GHz */ | ||
336 | freq_nearest = 1000000000; | ||
337 | |||
338 | /* | ||
339 | * Find the timings table such that: | ||
340 | * 1. the frequency range covers the required frequency(safe) AND | ||
341 | * 2. the max_freq is closest to the required frequency(optimal) | ||
342 | */ | ||
343 | for (i = 0; i < emif->plat_data->timings_arr_size; i++) { | ||
344 | max = timings_arr[i].max_freq; | ||
345 | min = timings_arr[i].min_freq; | ||
346 | if ((freq >= min) && (freq <= max) && (max < freq_nearest)) { | ||
347 | freq_nearest = max; | ||
348 | timings = &timings_arr[i]; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | if (!timings) | ||
353 | dev_err(dev, "%s: couldn't find timings for - %dHz\n", | ||
354 | __func__, freq); | ||
355 | |||
356 | dev_dbg(dev, "%s: timings table: freq %d, speed bin freq %d\n", | ||
357 | __func__, freq, freq_nearest); | ||
358 | |||
359 | return timings; | ||
360 | } | ||
361 | |||
362 | static u32 get_sdram_ref_ctrl_shdw(u32 freq, | ||
363 | const struct lpddr2_addressing *addressing) | ||
364 | { | ||
365 | u32 ref_ctrl_shdw = 0, val = 0, freq_khz, t_refi; | ||
366 | |||
367 | /* Scale down frequency and t_refi to avoid overflow */ | ||
368 | freq_khz = freq / 1000; | ||
369 | t_refi = addressing->tREFI_ns / 100; | ||
370 | |||
371 | /* | ||
372 | * refresh rate to be set is 'tREFI(in us) * freq in MHz | ||
373 | * division by 10000 to account for change in units | ||
374 | */ | ||
375 | val = t_refi * freq_khz / 10000; | ||
376 | ref_ctrl_shdw |= val << REFRESH_RATE_SHIFT; | ||
377 | |||
378 | return ref_ctrl_shdw; | ||
379 | } | ||
380 | |||
381 | static u32 get_sdram_tim_1_shdw(const struct lpddr2_timings *timings, | ||
382 | const struct lpddr2_min_tck *min_tck, | ||
383 | const struct lpddr2_addressing *addressing) | ||
384 | { | ||
385 | u32 tim1 = 0, val = 0; | ||
386 | |||
387 | val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1; | ||
388 | tim1 |= val << T_WTR_SHIFT; | ||
389 | |||
390 | if (addressing->num_banks == B8) | ||
391 | val = DIV_ROUND_UP(timings->tFAW, t_ck*4); | ||
392 | else | ||
393 | val = max(min_tck->tRRD, DIV_ROUND_UP(timings->tRRD, t_ck)); | ||
394 | tim1 |= (val - 1) << T_RRD_SHIFT; | ||
395 | |||
396 | val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab, t_ck) - 1; | ||
397 | tim1 |= val << T_RC_SHIFT; | ||
398 | |||
399 | val = max(min_tck->tRASmin, DIV_ROUND_UP(timings->tRAS_min, t_ck)); | ||
400 | tim1 |= (val - 1) << T_RAS_SHIFT; | ||
401 | |||
402 | val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1; | ||
403 | tim1 |= val << T_WR_SHIFT; | ||
404 | |||
405 | val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD, t_ck)) - 1; | ||
406 | tim1 |= val << T_RCD_SHIFT; | ||
407 | |||
408 | val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab, t_ck)) - 1; | ||
409 | tim1 |= val << T_RP_SHIFT; | ||
410 | |||
411 | return tim1; | ||
412 | } | ||
413 | |||
414 | static u32 get_sdram_tim_1_shdw_derated(const struct lpddr2_timings *timings, | ||
415 | const struct lpddr2_min_tck *min_tck, | ||
416 | const struct lpddr2_addressing *addressing) | ||
417 | { | ||
418 | u32 tim1 = 0, val = 0; | ||
419 | |||
420 | val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1; | ||
421 | tim1 = val << T_WTR_SHIFT; | ||
422 | |||
423 | /* | ||
424 | * tFAW is approximately 4 times tRRD. So add 1875*4 = 7500ps | ||
425 | * to tFAW for de-rating | ||
426 | */ | ||
427 | if (addressing->num_banks == B8) { | ||
428 | val = DIV_ROUND_UP(timings->tFAW + 7500, 4 * t_ck) - 1; | ||
429 | } else { | ||
430 | val = DIV_ROUND_UP(timings->tRRD + 1875, t_ck); | ||
431 | val = max(min_tck->tRRD, val) - 1; | ||
432 | } | ||
433 | tim1 |= val << T_RRD_SHIFT; | ||
434 | |||
435 | val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab + 1875, t_ck); | ||
436 | tim1 |= (val - 1) << T_RC_SHIFT; | ||
437 | |||
438 | val = DIV_ROUND_UP(timings->tRAS_min + 1875, t_ck); | ||
439 | val = max(min_tck->tRASmin, val) - 1; | ||
440 | tim1 |= val << T_RAS_SHIFT; | ||
441 | |||
442 | val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1; | ||
443 | tim1 |= val << T_WR_SHIFT; | ||
444 | |||
445 | val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD + 1875, t_ck)); | ||
446 | tim1 |= (val - 1) << T_RCD_SHIFT; | ||
447 | |||
448 | val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab + 1875, t_ck)); | ||
449 | tim1 |= (val - 1) << T_RP_SHIFT; | ||
450 | |||
451 | return tim1; | ||
452 | } | ||
453 | |||
454 | static u32 get_sdram_tim_2_shdw(const struct lpddr2_timings *timings, | ||
455 | const struct lpddr2_min_tck *min_tck, | ||
456 | const struct lpddr2_addressing *addressing, | ||
457 | u32 type) | ||
458 | { | ||
459 | u32 tim2 = 0, val = 0; | ||
460 | |||
461 | val = min_tck->tCKE - 1; | ||
462 | tim2 |= val << T_CKE_SHIFT; | ||
463 | |||
464 | val = max(min_tck->tRTP, DIV_ROUND_UP(timings->tRTP, t_ck)) - 1; | ||
465 | tim2 |= val << T_RTP_SHIFT; | ||
466 | |||
467 | /* tXSNR = tRFCab_ps + 10 ns(tRFCab_ps for LPDDR2). */ | ||
468 | val = DIV_ROUND_UP(addressing->tRFCab_ps + 10000, t_ck) - 1; | ||
469 | tim2 |= val << T_XSNR_SHIFT; | ||
470 | |||
471 | /* XSRD same as XSNR for LPDDR2 */ | ||
472 | tim2 |= val << T_XSRD_SHIFT; | ||
473 | |||
474 | val = max(min_tck->tXP, DIV_ROUND_UP(timings->tXP, t_ck)) - 1; | ||
475 | tim2 |= val << T_XP_SHIFT; | ||
476 | |||
477 | return tim2; | ||
478 | } | ||
479 | |||
480 | static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings, | ||
481 | const struct lpddr2_min_tck *min_tck, | ||
482 | const struct lpddr2_addressing *addressing, | ||
483 | u32 type, u32 ip_rev, u32 derated) | ||
484 | { | ||
485 | u32 tim3 = 0, val = 0, t_dqsck; | ||
486 | |||
487 | val = timings->tRAS_max_ns / addressing->tREFI_ns - 1; | ||
488 | val = val > 0xF ? 0xF : val; | ||
489 | tim3 |= val << T_RAS_MAX_SHIFT; | ||
490 | |||
491 | val = DIV_ROUND_UP(addressing->tRFCab_ps, t_ck) - 1; | ||
492 | tim3 |= val << T_RFC_SHIFT; | ||
493 | |||
494 | t_dqsck = (derated == EMIF_DERATED_TIMINGS) ? | ||
495 | timings->tDQSCK_max_derated : timings->tDQSCK_max; | ||
496 | if (ip_rev == EMIF_4D5) | ||
497 | val = DIV_ROUND_UP(t_dqsck + 1000, t_ck) - 1; | ||
498 | else | ||
499 | val = DIV_ROUND_UP(t_dqsck, t_ck) - 1; | ||
500 | |||
501 | tim3 |= val << T_TDQSCKMAX_SHIFT; | ||
502 | |||
503 | val = DIV_ROUND_UP(timings->tZQCS, t_ck) - 1; | ||
504 | tim3 |= val << ZQ_ZQCS_SHIFT; | ||
505 | |||
506 | val = DIV_ROUND_UP(timings->tCKESR, t_ck); | ||
507 | val = max(min_tck->tCKESR, val) - 1; | ||
508 | tim3 |= val << T_CKESR_SHIFT; | ||
509 | |||
510 | if (ip_rev == EMIF_4D5) { | ||
511 | tim3 |= (EMIF_T_CSTA - 1) << T_CSTA_SHIFT; | ||
512 | |||
513 | val = DIV_ROUND_UP(EMIF_T_PDLL_UL, 128) - 1; | ||
514 | tim3 |= val << T_PDLL_UL_SHIFT; | ||
515 | } | ||
516 | |||
517 | return tim3; | ||
518 | } | ||
519 | |||
520 | static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing, | ||
521 | bool cs1_used, bool cal_resistors_per_cs) | ||
522 | { | ||
523 | u32 zq = 0, val = 0; | ||
524 | |||
525 | val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing->tREFI_ns; | ||
526 | zq |= val << ZQ_REFINTERVAL_SHIFT; | ||
527 | |||
528 | val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1; | ||
529 | zq |= val << ZQ_ZQCL_MULT_SHIFT; | ||
530 | |||
531 | val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1; | ||
532 | zq |= val << ZQ_ZQINIT_MULT_SHIFT; | ||
533 | |||
534 | zq |= ZQ_SFEXITEN_ENABLE << ZQ_SFEXITEN_SHIFT; | ||
535 | |||
536 | if (cal_resistors_per_cs) | ||
537 | zq |= ZQ_DUALCALEN_ENABLE << ZQ_DUALCALEN_SHIFT; | ||
538 | else | ||
539 | zq |= ZQ_DUALCALEN_DISABLE << ZQ_DUALCALEN_SHIFT; | ||
540 | |||
541 | zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */ | ||
542 | |||
543 | val = cs1_used ? 1 : 0; | ||
544 | zq |= val << ZQ_CS1EN_SHIFT; | ||
545 | |||
546 | return zq; | ||
547 | } | ||
548 | |||
549 | static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing, | ||
550 | const struct emif_custom_configs *custom_configs, bool cs1_used, | ||
551 | u32 sdram_io_width, u32 emif_bus_width) | ||
552 | { | ||
553 | u32 alert = 0, interval, devcnt; | ||
554 | |||
555 | if (custom_configs && (custom_configs->mask & | ||
556 | EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)) | ||
557 | interval = custom_configs->temp_alert_poll_interval_ms; | ||
558 | else | ||
559 | interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS; | ||
560 | |||
561 | interval *= 1000000; /* Convert to ns */ | ||
562 | interval /= addressing->tREFI_ns; /* Convert to refresh cycles */ | ||
563 | alert |= (interval << TA_REFINTERVAL_SHIFT); | ||
564 | |||
565 | /* | ||
566 | * sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width | ||
567 | * also to this form and subtract to get TA_DEVCNT, which is | ||
568 | * in log2(x) form. | ||
569 | */ | ||
570 | emif_bus_width = __fls(emif_bus_width) - 1; | ||
571 | devcnt = emif_bus_width - sdram_io_width; | ||
572 | alert |= devcnt << TA_DEVCNT_SHIFT; | ||
573 | |||
574 | /* DEVWDT is in 'log2(x) - 3' form */ | ||
575 | alert |= (sdram_io_width - 2) << TA_DEVWDT_SHIFT; | ||
576 | |||
577 | alert |= 1 << TA_SFEXITEN_SHIFT; | ||
578 | alert |= 1 << TA_CS0EN_SHIFT; | ||
579 | alert |= (cs1_used ? 1 : 0) << TA_CS1EN_SHIFT; | ||
580 | |||
581 | return alert; | ||
582 | } | ||
583 | |||
584 | static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) | ||
585 | { | ||
586 | u32 idle = 0, val = 0; | ||
587 | |||
588 | /* | ||
589 | * Maximum value in normal conditions and increased frequency | ||
590 | * when voltage is ramping | ||
591 | */ | ||
592 | if (volt_ramp) | ||
593 | val = READ_IDLE_INTERVAL_DVFS / t_ck / 64 - 1; | ||
594 | else | ||
595 | val = 0x1FF; | ||
596 | |||
597 | /* | ||
598 | * READ_IDLE_CTRL register in EMIF4D has same offset and fields | ||
599 | * as DLL_CALIB_CTRL in EMIF4D5, so use the same shifts | ||
600 | */ | ||
601 | idle |= val << DLL_CALIB_INTERVAL_SHIFT; | ||
602 | idle |= EMIF_READ_IDLE_LEN_VAL << ACK_WAIT_SHIFT; | ||
603 | |||
604 | return idle; | ||
605 | } | ||
606 | |||
607 | static u32 get_dll_calib_ctrl_shdw(u8 volt_ramp) | ||
608 | { | ||
609 | u32 calib = 0, val = 0; | ||
610 | |||
611 | if (volt_ramp == DDR_VOLTAGE_RAMPING) | ||
612 | val = DLL_CALIB_INTERVAL_DVFS / t_ck / 16 - 1; | ||
613 | else | ||
614 | val = 0; /* Disabled when voltage is stable */ | ||
615 | |||
616 | calib |= val << DLL_CALIB_INTERVAL_SHIFT; | ||
617 | calib |= DLL_CALIB_ACK_WAIT_VAL << ACK_WAIT_SHIFT; | ||
618 | |||
619 | return calib; | ||
620 | } | ||
621 | |||
622 | static u32 get_ddr_phy_ctrl_1_attilaphy_4d(const struct lpddr2_timings *timings, | ||
623 | u32 freq, u8 RL) | ||
624 | { | ||
625 | u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY, val = 0; | ||
626 | |||
627 | val = RL + DIV_ROUND_UP(timings->tDQSCK_max, t_ck) - 1; | ||
628 | phy |= val << READ_LATENCY_SHIFT_4D; | ||
629 | |||
630 | if (freq <= 100000000) | ||
631 | val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY; | ||
632 | else if (freq <= 200000000) | ||
633 | val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY; | ||
634 | else | ||
635 | val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY; | ||
636 | |||
637 | phy |= val << DLL_SLAVE_DLY_CTRL_SHIFT_4D; | ||
638 | |||
639 | return phy; | ||
640 | } | ||
641 | |||
642 | static u32 get_phy_ctrl_1_intelliphy_4d5(u32 freq, u8 cl) | ||
643 | { | ||
644 | u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY, half_delay; | ||
645 | |||
646 | /* | ||
647 | * DLL operates at 266 MHz. If DDR frequency is near 266 MHz, | ||
648 | * half-delay is not needed else set half-delay | ||
649 | */ | ||
650 | if (freq >= 265000000 && freq < 267000000) | ||
651 | half_delay = 0; | ||
652 | else | ||
653 | half_delay = 1; | ||
654 | |||
655 | phy |= half_delay << DLL_HALF_DELAY_SHIFT_4D5; | ||
656 | phy |= ((cl + DIV_ROUND_UP(EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS, | ||
657 | t_ck) - 1) << READ_LATENCY_SHIFT_4D5); | ||
658 | |||
659 | return phy; | ||
660 | } | ||
661 | |||
662 | static u32 get_ext_phy_ctrl_2_intelliphy_4d5(void) | ||
663 | { | ||
664 | u32 fifo_we_slave_ratio; | ||
665 | |||
666 | fifo_we_slave_ratio = DIV_ROUND_CLOSEST( | ||
667 | EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck); | ||
668 | |||
669 | return fifo_we_slave_ratio | fifo_we_slave_ratio << 11 | | ||
670 | fifo_we_slave_ratio << 22; | ||
671 | } | ||
672 | |||
673 | static u32 get_ext_phy_ctrl_3_intelliphy_4d5(void) | ||
674 | { | ||
675 | u32 fifo_we_slave_ratio; | ||
676 | |||
677 | fifo_we_slave_ratio = DIV_ROUND_CLOSEST( | ||
678 | EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck); | ||
679 | |||
680 | return fifo_we_slave_ratio >> 10 | fifo_we_slave_ratio << 1 | | ||
681 | fifo_we_slave_ratio << 12 | fifo_we_slave_ratio << 23; | ||
682 | } | ||
683 | |||
684 | static u32 get_ext_phy_ctrl_4_intelliphy_4d5(void) | ||
685 | { | ||
686 | u32 fifo_we_slave_ratio; | ||
687 | |||
688 | fifo_we_slave_ratio = DIV_ROUND_CLOSEST( | ||
689 | EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck); | ||
690 | |||
691 | return fifo_we_slave_ratio >> 9 | fifo_we_slave_ratio << 2 | | ||
692 | fifo_we_slave_ratio << 13; | ||
693 | } | ||
694 | |||
695 | static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) | ||
696 | { | ||
697 | u32 pwr_mgmt_ctrl = 0, timeout; | ||
698 | u32 lpmode = EMIF_LP_MODE_SELF_REFRESH; | ||
699 | u32 timeout_perf = EMIF_LP_MODE_TIMEOUT_PERFORMANCE; | ||
700 | u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER; | ||
701 | u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD; | ||
702 | |||
703 | struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs; | ||
704 | |||
705 | if (cust_cfgs && (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE)) { | ||
706 | lpmode = cust_cfgs->lpmode; | ||
707 | timeout_perf = cust_cfgs->lpmode_timeout_performance; | ||
708 | timeout_pwr = cust_cfgs->lpmode_timeout_power; | ||
709 | freq_threshold = cust_cfgs->lpmode_freq_threshold; | ||
710 | } | ||
711 | |||
712 | /* Timeout based on DDR frequency */ | ||
713 | timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr; | ||
714 | |||
715 | /* The value to be set in register is "log2(timeout) - 3" */ | ||
716 | if (timeout < 16) { | ||
717 | timeout = 0; | ||
718 | } else { | ||
719 | timeout = __fls(timeout) - 3; | ||
720 | if (timeout & (timeout - 1)) | ||
721 | timeout++; | ||
722 | } | ||
723 | |||
724 | switch (lpmode) { | ||
725 | case EMIF_LP_MODE_CLOCK_STOP: | ||
726 | pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) | | ||
727 | SR_TIM_MASK | PD_TIM_MASK; | ||
728 | break; | ||
729 | case EMIF_LP_MODE_SELF_REFRESH: | ||
730 | /* Workaround for errata i735 */ | ||
731 | if (timeout < 6) | ||
732 | timeout = 6; | ||
733 | |||
734 | pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) | | ||
735 | CS_TIM_MASK | PD_TIM_MASK; | ||
736 | break; | ||
737 | case EMIF_LP_MODE_PWR_DN: | ||
738 | pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) | | ||
739 | CS_TIM_MASK | SR_TIM_MASK; | ||
740 | break; | ||
741 | case EMIF_LP_MODE_DISABLE: | ||
742 | default: | ||
743 | pwr_mgmt_ctrl = CS_TIM_MASK | | ||
744 | PD_TIM_MASK | SR_TIM_MASK; | ||
745 | } | ||
746 | |||
747 | /* No CS_TIM in EMIF_4D5 */ | ||
748 | if (ip_rev == EMIF_4D5) | ||
749 | pwr_mgmt_ctrl &= ~CS_TIM_MASK; | ||
750 | |||
751 | pwr_mgmt_ctrl |= lpmode << LP_MODE_SHIFT; | ||
752 | |||
753 | return pwr_mgmt_ctrl; | ||
754 | } | ||
755 | |||
756 | /* | ||
757 | * Get the temperature level of the EMIF instance: | ||
758 | * Reads the MR4 register of attached SDRAM parts to find out the temperature | ||
759 | * level. If there are two parts attached(one on each CS), then the temperature | ||
760 | * level for the EMIF instance is the higher of the two temperatures. | ||
761 | */ | ||
762 | static void get_temperature_level(struct emif_data *emif) | ||
763 | { | ||
764 | u32 temp, temperature_level; | ||
765 | void __iomem *base; | ||
766 | |||
767 | base = emif->base; | ||
768 | |||
769 | /* Read mode register 4 */ | ||
770 | writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG); | ||
771 | temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA); | ||
772 | temperature_level = (temperature_level & MR4_SDRAM_REF_RATE_MASK) >> | ||
773 | MR4_SDRAM_REF_RATE_SHIFT; | ||
774 | |||
775 | if (emif->plat_data->device_info->cs1_used) { | ||
776 | writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG); | ||
777 | temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA); | ||
778 | temp = (temp & MR4_SDRAM_REF_RATE_MASK) | ||
779 | >> MR4_SDRAM_REF_RATE_SHIFT; | ||
780 | temperature_level = max(temp, temperature_level); | ||
781 | } | ||
782 | |||
783 | /* treat everything less than nominal(3) in MR4 as nominal */ | ||
784 | if (unlikely(temperature_level < SDRAM_TEMP_NOMINAL)) | ||
785 | temperature_level = SDRAM_TEMP_NOMINAL; | ||
786 | |||
787 | /* if we get reserved value in MR4 persist with the existing value */ | ||
788 | if (likely(temperature_level != SDRAM_TEMP_RESERVED_4)) | ||
789 | emif->temperature_level = temperature_level; | ||
790 | } | ||
791 | |||
792 | /* | ||
793 | * Program EMIF shadow registers that are not dependent on temperature | ||
794 | * or voltage | ||
795 | */ | ||
796 | static void setup_registers(struct emif_data *emif, struct emif_regs *regs) | ||
797 | { | ||
798 | void __iomem *base = emif->base; | ||
799 | |||
800 | writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW); | ||
801 | writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW); | ||
802 | |||
803 | /* Settings specific for EMIF4D5 */ | ||
804 | if (emif->plat_data->ip_rev != EMIF_4D5) | ||
805 | return; | ||
806 | writel(regs->ext_phy_ctrl_2_shdw, base + EMIF_EXT_PHY_CTRL_2_SHDW); | ||
807 | writel(regs->ext_phy_ctrl_3_shdw, base + EMIF_EXT_PHY_CTRL_3_SHDW); | ||
808 | writel(regs->ext_phy_ctrl_4_shdw, base + EMIF_EXT_PHY_CTRL_4_SHDW); | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * When voltage ramps dll calibration and forced read idle should | ||
813 | * happen more often | ||
814 | */ | ||
815 | static void setup_volt_sensitive_regs(struct emif_data *emif, | ||
816 | struct emif_regs *regs, u32 volt_state) | ||
817 | { | ||
818 | u32 calib_ctrl; | ||
819 | void __iomem *base = emif->base; | ||
820 | |||
821 | /* | ||
822 | * EMIF_READ_IDLE_CTRL in EMIF4D refers to the same register as | ||
823 | * EMIF_DLL_CALIB_CTRL in EMIF4D5 and dll_calib_ctrl_shadow_* | ||
824 | * is an alias of the respective read_idle_ctrl_shdw_* (members of | ||
825 | * a union). So, the below code takes care of both cases | ||
826 | */ | ||
827 | if (volt_state == DDR_VOLTAGE_RAMPING) | ||
828 | calib_ctrl = regs->dll_calib_ctrl_shdw_volt_ramp; | ||
829 | else | ||
830 | calib_ctrl = regs->dll_calib_ctrl_shdw_normal; | ||
831 | |||
832 | writel(calib_ctrl, base + EMIF_DLL_CALIB_CTRL_SHDW); | ||
833 | } | ||
834 | |||
835 | /* | ||
836 | * setup_temperature_sensitive_regs() - set the timings for temperature | ||
837 | * sensitive registers. This happens once at initialisation time based | ||
838 | * on the temperature at boot time and subsequently based on the temperature | ||
839 | * alert interrupt. Temperature alert can happen when the temperature | ||
840 | * increases or drops. So this function can have the effect of either | ||
841 | * derating the timings or going back to nominal values. | ||
842 | */ | ||
843 | static void setup_temperature_sensitive_regs(struct emif_data *emif, | ||
844 | struct emif_regs *regs) | ||
845 | { | ||
846 | u32 tim1, tim3, ref_ctrl, type; | ||
847 | void __iomem *base = emif->base; | ||
848 | u32 temperature; | ||
849 | |||
850 | type = emif->plat_data->device_info->type; | ||
851 | |||
852 | tim1 = regs->sdram_tim1_shdw; | ||
853 | tim3 = regs->sdram_tim3_shdw; | ||
854 | ref_ctrl = regs->ref_ctrl_shdw; | ||
855 | |||
856 | /* No de-rating for non-lpddr2 devices */ | ||
857 | if (type != DDR_TYPE_LPDDR2_S2 && type != DDR_TYPE_LPDDR2_S4) | ||
858 | goto out; | ||
859 | |||
860 | temperature = emif->temperature_level; | ||
861 | if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH) { | ||
862 | ref_ctrl = regs->ref_ctrl_shdw_derated; | ||
863 | } else if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS) { | ||
864 | tim1 = regs->sdram_tim1_shdw_derated; | ||
865 | tim3 = regs->sdram_tim3_shdw_derated; | ||
866 | ref_ctrl = regs->ref_ctrl_shdw_derated; | ||
867 | } | ||
868 | |||
869 | out: | ||
870 | writel(tim1, base + EMIF_SDRAM_TIMING_1_SHDW); | ||
871 | writel(tim3, base + EMIF_SDRAM_TIMING_3_SHDW); | ||
872 | writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW); | ||
873 | } | ||
874 | |||
875 | static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) | ||
876 | { | ||
877 | u32 old_temp_level; | ||
878 | irqreturn_t ret = IRQ_HANDLED; | ||
879 | |||
880 | spin_lock_irqsave(&emif_lock, irq_state); | ||
881 | old_temp_level = emif->temperature_level; | ||
882 | get_temperature_level(emif); | ||
883 | |||
884 | if (unlikely(emif->temperature_level == old_temp_level)) { | ||
885 | goto out; | ||
886 | } else if (!emif->curr_regs) { | ||
887 | dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n"); | ||
888 | goto out; | ||
889 | } | ||
890 | |||
891 | if (emif->temperature_level < old_temp_level || | ||
892 | emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { | ||
893 | /* | ||
894 | * Temperature coming down - defer handling to thread OR | ||
895 | * Temperature far too high - do kernel_power_off() from | ||
896 | * thread context | ||
897 | */ | ||
898 | ret = IRQ_WAKE_THREAD; | ||
899 | } else { | ||
900 | /* Temperature is going up - handle immediately */ | ||
901 | setup_temperature_sensitive_regs(emif, emif->curr_regs); | ||
902 | do_freq_update(); | ||
903 | } | ||
904 | |||
905 | out: | ||
906 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
907 | return ret; | ||
908 | } | ||
909 | |||
910 | static irqreturn_t emif_interrupt_handler(int irq, void *dev_id) | ||
911 | { | ||
912 | u32 interrupts; | ||
913 | struct emif_data *emif = dev_id; | ||
914 | void __iomem *base = emif->base; | ||
915 | struct device *dev = emif->dev; | ||
916 | irqreturn_t ret = IRQ_HANDLED; | ||
917 | |||
918 | /* Save the status and clear it */ | ||
919 | interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); | ||
920 | writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); | ||
921 | |||
922 | /* | ||
923 | * Handle temperature alert | ||
924 | * Temperature alert should be same for all ports | ||
925 | * So, it's enough to process it only for one of the ports | ||
926 | */ | ||
927 | if (interrupts & TA_SYS_MASK) | ||
928 | ret = handle_temp_alert(base, emif); | ||
929 | |||
930 | if (interrupts & ERR_SYS_MASK) | ||
931 | dev_err(dev, "Access error from SYS port - %x\n", interrupts); | ||
932 | |||
933 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) { | ||
934 | /* Save the status and clear it */ | ||
935 | interrupts = readl(base + EMIF_LL_OCP_INTERRUPT_STATUS); | ||
936 | writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_STATUS); | ||
937 | |||
938 | if (interrupts & ERR_LL_MASK) | ||
939 | dev_err(dev, "Access error from LL port - %x\n", | ||
940 | interrupts); | ||
941 | } | ||
942 | |||
943 | return ret; | ||
944 | } | ||
945 | |||
946 | static irqreturn_t emif_threaded_isr(int irq, void *dev_id) | ||
947 | { | ||
948 | struct emif_data *emif = dev_id; | ||
949 | |||
950 | if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { | ||
951 | dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); | ||
952 | kernel_power_off(); | ||
953 | return IRQ_HANDLED; | ||
954 | } | ||
955 | |||
956 | spin_lock_irqsave(&emif_lock, irq_state); | ||
957 | |||
958 | if (emif->curr_regs) { | ||
959 | setup_temperature_sensitive_regs(emif, emif->curr_regs); | ||
960 | do_freq_update(); | ||
961 | } else { | ||
962 | dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n"); | ||
963 | } | ||
964 | |||
965 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
966 | |||
967 | return IRQ_HANDLED; | ||
968 | } | ||
969 | |||
970 | static void clear_all_interrupts(struct emif_data *emif) | ||
971 | { | ||
972 | void __iomem *base = emif->base; | ||
973 | |||
974 | writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS), | ||
975 | base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS); | ||
976 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) | ||
977 | writel(readl(base + EMIF_LL_OCP_INTERRUPT_STATUS), | ||
978 | base + EMIF_LL_OCP_INTERRUPT_STATUS); | ||
979 | } | ||
980 | |||
981 | static void disable_and_clear_all_interrupts(struct emif_data *emif) | ||
982 | { | ||
983 | void __iomem *base = emif->base; | ||
984 | |||
985 | /* Disable all interrupts */ | ||
986 | writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET), | ||
987 | base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR); | ||
988 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) | ||
989 | writel(readl(base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET), | ||
990 | base + EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR); | ||
991 | |||
992 | /* Clear all interrupts */ | ||
993 | clear_all_interrupts(emif); | ||
994 | } | ||
995 | |||
996 | static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq) | ||
997 | { | ||
998 | u32 interrupts, type; | ||
999 | void __iomem *base = emif->base; | ||
1000 | |||
1001 | type = emif->plat_data->device_info->type; | ||
1002 | |||
1003 | clear_all_interrupts(emif); | ||
1004 | |||
1005 | /* Enable interrupts for SYS interface */ | ||
1006 | interrupts = EN_ERR_SYS_MASK; | ||
1007 | if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) | ||
1008 | interrupts |= EN_TA_SYS_MASK; | ||
1009 | writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET); | ||
1010 | |||
1011 | /* Enable interrupts for LL interface */ | ||
1012 | if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) { | ||
1013 | /* TA need not be enabled for LL */ | ||
1014 | interrupts = EN_ERR_LL_MASK; | ||
1015 | writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET); | ||
1016 | } | ||
1017 | |||
1018 | /* setup IRQ handlers */ | ||
1019 | return devm_request_threaded_irq(emif->dev, irq, | ||
1020 | emif_interrupt_handler, | ||
1021 | emif_threaded_isr, | ||
1022 | 0, dev_name(emif->dev), | ||
1023 | emif); | ||
1024 | |||
1025 | } | ||
1026 | |||
1027 | static void __init_or_module emif_onetime_settings(struct emif_data *emif) | ||
1028 | { | ||
1029 | u32 pwr_mgmt_ctrl, zq, temp_alert_cfg; | ||
1030 | void __iomem *base = emif->base; | ||
1031 | const struct lpddr2_addressing *addressing; | ||
1032 | const struct ddr_device_info *device_info; | ||
1033 | |||
1034 | device_info = emif->plat_data->device_info; | ||
1035 | addressing = get_addressing_table(device_info); | ||
1036 | |||
1037 | /* | ||
1038 | * Init power management settings | ||
1039 | * We don't know the frequency yet. Use a high frequency | ||
1040 | * value for a conservative timeout setting | ||
1041 | */ | ||
1042 | pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(1000000000, emif, | ||
1043 | emif->plat_data->ip_rev); | ||
1044 | emif->lpmode = (pwr_mgmt_ctrl & LP_MODE_MASK) >> LP_MODE_SHIFT; | ||
1045 | writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL); | ||
1046 | |||
1047 | /* Init ZQ calibration settings */ | ||
1048 | zq = get_zq_config_reg(addressing, device_info->cs1_used, | ||
1049 | device_info->cal_resistors_per_cs); | ||
1050 | writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG); | ||
1051 | |||
1052 | /* Check temperature level temperature level*/ | ||
1053 | get_temperature_level(emif); | ||
1054 | if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) | ||
1055 | dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); | ||
1056 | |||
1057 | /* Init temperature polling */ | ||
1058 | temp_alert_cfg = get_temp_alert_config(addressing, | ||
1059 | emif->plat_data->custom_configs, device_info->cs1_used, | ||
1060 | device_info->io_width, get_emif_bus_width(emif)); | ||
1061 | writel(temp_alert_cfg, base + EMIF_TEMPERATURE_ALERT_CONFIG); | ||
1062 | |||
1063 | /* | ||
1064 | * Program external PHY control registers that are not frequency | ||
1065 | * dependent | ||
1066 | */ | ||
1067 | if (emif->plat_data->phy_type != EMIF_PHY_TYPE_INTELLIPHY) | ||
1068 | return; | ||
1069 | writel(EMIF_EXT_PHY_CTRL_1_VAL, base + EMIF_EXT_PHY_CTRL_1_SHDW); | ||
1070 | writel(EMIF_EXT_PHY_CTRL_5_VAL, base + EMIF_EXT_PHY_CTRL_5_SHDW); | ||
1071 | writel(EMIF_EXT_PHY_CTRL_6_VAL, base + EMIF_EXT_PHY_CTRL_6_SHDW); | ||
1072 | writel(EMIF_EXT_PHY_CTRL_7_VAL, base + EMIF_EXT_PHY_CTRL_7_SHDW); | ||
1073 | writel(EMIF_EXT_PHY_CTRL_8_VAL, base + EMIF_EXT_PHY_CTRL_8_SHDW); | ||
1074 | writel(EMIF_EXT_PHY_CTRL_9_VAL, base + EMIF_EXT_PHY_CTRL_9_SHDW); | ||
1075 | writel(EMIF_EXT_PHY_CTRL_10_VAL, base + EMIF_EXT_PHY_CTRL_10_SHDW); | ||
1076 | writel(EMIF_EXT_PHY_CTRL_11_VAL, base + EMIF_EXT_PHY_CTRL_11_SHDW); | ||
1077 | writel(EMIF_EXT_PHY_CTRL_12_VAL, base + EMIF_EXT_PHY_CTRL_12_SHDW); | ||
1078 | writel(EMIF_EXT_PHY_CTRL_13_VAL, base + EMIF_EXT_PHY_CTRL_13_SHDW); | ||
1079 | writel(EMIF_EXT_PHY_CTRL_14_VAL, base + EMIF_EXT_PHY_CTRL_14_SHDW); | ||
1080 | writel(EMIF_EXT_PHY_CTRL_15_VAL, base + EMIF_EXT_PHY_CTRL_15_SHDW); | ||
1081 | writel(EMIF_EXT_PHY_CTRL_16_VAL, base + EMIF_EXT_PHY_CTRL_16_SHDW); | ||
1082 | writel(EMIF_EXT_PHY_CTRL_17_VAL, base + EMIF_EXT_PHY_CTRL_17_SHDW); | ||
1083 | writel(EMIF_EXT_PHY_CTRL_18_VAL, base + EMIF_EXT_PHY_CTRL_18_SHDW); | ||
1084 | writel(EMIF_EXT_PHY_CTRL_19_VAL, base + EMIF_EXT_PHY_CTRL_19_SHDW); | ||
1085 | writel(EMIF_EXT_PHY_CTRL_20_VAL, base + EMIF_EXT_PHY_CTRL_20_SHDW); | ||
1086 | writel(EMIF_EXT_PHY_CTRL_21_VAL, base + EMIF_EXT_PHY_CTRL_21_SHDW); | ||
1087 | writel(EMIF_EXT_PHY_CTRL_22_VAL, base + EMIF_EXT_PHY_CTRL_22_SHDW); | ||
1088 | writel(EMIF_EXT_PHY_CTRL_23_VAL, base + EMIF_EXT_PHY_CTRL_23_SHDW); | ||
1089 | writel(EMIF_EXT_PHY_CTRL_24_VAL, base + EMIF_EXT_PHY_CTRL_24_SHDW); | ||
1090 | } | ||
1091 | |||
1092 | static void get_default_timings(struct emif_data *emif) | ||
1093 | { | ||
1094 | struct emif_platform_data *pd = emif->plat_data; | ||
1095 | |||
1096 | pd->timings = lpddr2_jedec_timings; | ||
1097 | pd->timings_arr_size = ARRAY_SIZE(lpddr2_jedec_timings); | ||
1098 | |||
1099 | dev_warn(emif->dev, "%s: using default timings\n", __func__); | ||
1100 | } | ||
1101 | |||
1102 | static int is_dev_data_valid(u32 type, u32 density, u32 io_width, u32 phy_type, | ||
1103 | u32 ip_rev, struct device *dev) | ||
1104 | { | ||
1105 | int valid; | ||
1106 | |||
1107 | valid = (type == DDR_TYPE_LPDDR2_S4 || | ||
1108 | type == DDR_TYPE_LPDDR2_S2) | ||
1109 | && (density >= DDR_DENSITY_64Mb | ||
1110 | && density <= DDR_DENSITY_8Gb) | ||
1111 | && (io_width >= DDR_IO_WIDTH_8 | ||
1112 | && io_width <= DDR_IO_WIDTH_32); | ||
1113 | |||
1114 | /* Combinations of EMIF and PHY revisions that we support today */ | ||
1115 | switch (ip_rev) { | ||
1116 | case EMIF_4D: | ||
1117 | valid = valid && (phy_type == EMIF_PHY_TYPE_ATTILAPHY); | ||
1118 | break; | ||
1119 | case EMIF_4D5: | ||
1120 | valid = valid && (phy_type == EMIF_PHY_TYPE_INTELLIPHY); | ||
1121 | break; | ||
1122 | default: | ||
1123 | valid = 0; | ||
1124 | } | ||
1125 | |||
1126 | if (!valid) | ||
1127 | dev_err(dev, "%s: invalid DDR details\n", __func__); | ||
1128 | return valid; | ||
1129 | } | ||
1130 | |||
1131 | static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, | ||
1132 | struct device *dev) | ||
1133 | { | ||
1134 | int valid = 1; | ||
1135 | |||
1136 | if ((cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE) && | ||
1137 | (cust_cfgs->lpmode != EMIF_LP_MODE_DISABLE)) | ||
1138 | valid = cust_cfgs->lpmode_freq_threshold && | ||
1139 | cust_cfgs->lpmode_timeout_performance && | ||
1140 | cust_cfgs->lpmode_timeout_power; | ||
1141 | |||
1142 | if (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL) | ||
1143 | valid = valid && cust_cfgs->temp_alert_poll_interval_ms; | ||
1144 | |||
1145 | if (!valid) | ||
1146 | dev_warn(dev, "%s: invalid custom configs\n", __func__); | ||
1147 | |||
1148 | return valid; | ||
1149 | } | ||
1150 | |||
1151 | static struct emif_data *__init_or_module get_device_details( | ||
1152 | struct platform_device *pdev) | ||
1153 | { | ||
1154 | u32 size; | ||
1155 | struct emif_data *emif = NULL; | ||
1156 | struct ddr_device_info *dev_info; | ||
1157 | struct emif_custom_configs *cust_cfgs; | ||
1158 | struct emif_platform_data *pd; | ||
1159 | struct device *dev; | ||
1160 | void *temp; | ||
1161 | |||
1162 | pd = pdev->dev.platform_data; | ||
1163 | dev = &pdev->dev; | ||
1164 | |||
1165 | if (!(pd && pd->device_info && is_dev_data_valid(pd->device_info->type, | ||
1166 | pd->device_info->density, pd->device_info->io_width, | ||
1167 | pd->phy_type, pd->ip_rev, dev))) { | ||
1168 | dev_err(dev, "%s: invalid device data\n", __func__); | ||
1169 | goto error; | ||
1170 | } | ||
1171 | |||
1172 | emif = devm_kzalloc(dev, sizeof(*emif), GFP_KERNEL); | ||
1173 | temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); | ||
1174 | dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL); | ||
1175 | |||
1176 | if (!emif || !pd || !dev_info) { | ||
1177 | dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__); | ||
1178 | goto error; | ||
1179 | } | ||
1180 | |||
1181 | memcpy(temp, pd, sizeof(*pd)); | ||
1182 | pd = temp; | ||
1183 | memcpy(dev_info, pd->device_info, sizeof(*dev_info)); | ||
1184 | |||
1185 | pd->device_info = dev_info; | ||
1186 | emif->plat_data = pd; | ||
1187 | emif->dev = dev; | ||
1188 | emif->temperature_level = SDRAM_TEMP_NOMINAL; | ||
1189 | |||
1190 | /* | ||
1191 | * For EMIF instances other than EMIF1 see if the devices connected | ||
1192 | * are exactly same as on EMIF1(which is typically the case). If so, | ||
1193 | * mark it as a duplicate of EMIF1 and skip copying timings data. | ||
1194 | * This will save some memory and some computation later. | ||
1195 | */ | ||
1196 | emif->duplicate = emif1 && (memcmp(dev_info, | ||
1197 | emif1->plat_data->device_info, | ||
1198 | sizeof(struct ddr_device_info)) == 0); | ||
1199 | |||
1200 | if (emif->duplicate) { | ||
1201 | pd->timings = NULL; | ||
1202 | pd->min_tck = NULL; | ||
1203 | goto out; | ||
1204 | } else if (emif1) { | ||
1205 | dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n", | ||
1206 | __func__); | ||
1207 | } | ||
1208 | |||
1209 | /* | ||
1210 | * Copy custom configs - ignore allocation error, if any, as | ||
1211 | * custom_configs is not very critical | ||
1212 | */ | ||
1213 | cust_cfgs = pd->custom_configs; | ||
1214 | if (cust_cfgs && is_custom_config_valid(cust_cfgs, dev)) { | ||
1215 | temp = devm_kzalloc(dev, sizeof(*cust_cfgs), GFP_KERNEL); | ||
1216 | if (temp) | ||
1217 | memcpy(temp, cust_cfgs, sizeof(*cust_cfgs)); | ||
1218 | else | ||
1219 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
1220 | __LINE__); | ||
1221 | pd->custom_configs = temp; | ||
1222 | } | ||
1223 | |||
1224 | /* | ||
1225 | * Copy timings and min-tck values from platform data. If it is not | ||
1226 | * available or if memory allocation fails, use JEDEC defaults | ||
1227 | */ | ||
1228 | size = sizeof(struct lpddr2_timings) * pd->timings_arr_size; | ||
1229 | if (pd->timings) { | ||
1230 | temp = devm_kzalloc(dev, size, GFP_KERNEL); | ||
1231 | if (temp) { | ||
1232 | memcpy(temp, pd->timings, sizeof(*pd->timings)); | ||
1233 | pd->timings = temp; | ||
1234 | } else { | ||
1235 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
1236 | __LINE__); | ||
1237 | get_default_timings(emif); | ||
1238 | } | ||
1239 | } else { | ||
1240 | get_default_timings(emif); | ||
1241 | } | ||
1242 | |||
1243 | if (pd->min_tck) { | ||
1244 | temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL); | ||
1245 | if (temp) { | ||
1246 | memcpy(temp, pd->min_tck, sizeof(*pd->min_tck)); | ||
1247 | pd->min_tck = temp; | ||
1248 | } else { | ||
1249 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
1250 | __LINE__); | ||
1251 | pd->min_tck = &lpddr2_jedec_min_tck; | ||
1252 | } | ||
1253 | } else { | ||
1254 | pd->min_tck = &lpddr2_jedec_min_tck; | ||
1255 | } | ||
1256 | |||
1257 | out: | ||
1258 | return emif; | ||
1259 | |||
1260 | error: | ||
1261 | return NULL; | ||
1262 | } | ||
1263 | |||
1264 | static int __init_or_module emif_probe(struct platform_device *pdev) | ||
1265 | { | ||
1266 | struct emif_data *emif; | ||
1267 | struct resource *res; | ||
1268 | int irq; | ||
1269 | |||
1270 | emif = get_device_details(pdev); | ||
1271 | if (!emif) { | ||
1272 | pr_err("%s: error getting device data\n", __func__); | ||
1273 | goto error; | ||
1274 | } | ||
1275 | |||
1276 | list_add(&emif->node, &device_list); | ||
1277 | emif->addressing = get_addressing_table(emif->plat_data->device_info); | ||
1278 | |||
1279 | /* Save pointers to each other in emif and device structures */ | ||
1280 | emif->dev = &pdev->dev; | ||
1281 | platform_set_drvdata(pdev, emif); | ||
1282 | |||
1283 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1284 | if (!res) { | ||
1285 | dev_err(emif->dev, "%s: error getting memory resource\n", | ||
1286 | __func__); | ||
1287 | goto error; | ||
1288 | } | ||
1289 | |||
1290 | emif->base = devm_request_and_ioremap(emif->dev, res); | ||
1291 | if (!emif->base) { | ||
1292 | dev_err(emif->dev, "%s: devm_request_and_ioremap() failed\n", | ||
1293 | __func__); | ||
1294 | goto error; | ||
1295 | } | ||
1296 | |||
1297 | irq = platform_get_irq(pdev, 0); | ||
1298 | if (irq < 0) { | ||
1299 | dev_err(emif->dev, "%s: error getting IRQ resource - %d\n", | ||
1300 | __func__, irq); | ||
1301 | goto error; | ||
1302 | } | ||
1303 | |||
1304 | emif_onetime_settings(emif); | ||
1305 | emif_debugfs_init(emif); | ||
1306 | disable_and_clear_all_interrupts(emif); | ||
1307 | setup_interrupts(emif, irq); | ||
1308 | |||
1309 | /* One-time actions taken on probing the first device */ | ||
1310 | if (!emif1) { | ||
1311 | emif1 = emif; | ||
1312 | spin_lock_init(&emif_lock); | ||
1313 | |||
1314 | /* | ||
1315 | * TODO: register notifiers for frequency and voltage | ||
1316 | * change here once the respective frameworks are | ||
1317 | * available | ||
1318 | */ | ||
1319 | } | ||
1320 | |||
1321 | dev_info(&pdev->dev, "%s: device configured with addr = %p and IRQ%d\n", | ||
1322 | __func__, emif->base, irq); | ||
1323 | |||
1324 | return 0; | ||
1325 | error: | ||
1326 | return -ENODEV; | ||
1327 | } | ||
1328 | |||
1329 | static int __exit emif_remove(struct platform_device *pdev) | ||
1330 | { | ||
1331 | struct emif_data *emif = platform_get_drvdata(pdev); | ||
1332 | |||
1333 | emif_debugfs_exit(emif); | ||
1334 | |||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
1338 | static void emif_shutdown(struct platform_device *pdev) | ||
1339 | { | ||
1340 | struct emif_data *emif = platform_get_drvdata(pdev); | ||
1341 | |||
1342 | disable_and_clear_all_interrupts(emif); | ||
1343 | } | ||
1344 | |||
1345 | static int get_emif_reg_values(struct emif_data *emif, u32 freq, | ||
1346 | struct emif_regs *regs) | ||
1347 | { | ||
1348 | u32 cs1_used, ip_rev, phy_type; | ||
1349 | u32 cl, type; | ||
1350 | const struct lpddr2_timings *timings; | ||
1351 | const struct lpddr2_min_tck *min_tck; | ||
1352 | const struct ddr_device_info *device_info; | ||
1353 | const struct lpddr2_addressing *addressing; | ||
1354 | struct emif_data *emif_for_calc; | ||
1355 | struct device *dev; | ||
1356 | const struct emif_custom_configs *custom_configs; | ||
1357 | |||
1358 | dev = emif->dev; | ||
1359 | /* | ||
1360 | * If the devices on this EMIF instance is duplicate of EMIF1, | ||
1361 | * use EMIF1 details for the calculation | ||
1362 | */ | ||
1363 | emif_for_calc = emif->duplicate ? emif1 : emif; | ||
1364 | timings = get_timings_table(emif_for_calc, freq); | ||
1365 | addressing = emif_for_calc->addressing; | ||
1366 | if (!timings || !addressing) { | ||
1367 | dev_err(dev, "%s: not enough data available for %dHz", | ||
1368 | __func__, freq); | ||
1369 | return -1; | ||
1370 | } | ||
1371 | |||
1372 | device_info = emif_for_calc->plat_data->device_info; | ||
1373 | type = device_info->type; | ||
1374 | cs1_used = device_info->cs1_used; | ||
1375 | ip_rev = emif_for_calc->plat_data->ip_rev; | ||
1376 | phy_type = emif_for_calc->plat_data->phy_type; | ||
1377 | |||
1378 | min_tck = emif_for_calc->plat_data->min_tck; | ||
1379 | custom_configs = emif_for_calc->plat_data->custom_configs; | ||
1380 | |||
1381 | set_ddr_clk_period(freq); | ||
1382 | |||
1383 | regs->ref_ctrl_shdw = get_sdram_ref_ctrl_shdw(freq, addressing); | ||
1384 | regs->sdram_tim1_shdw = get_sdram_tim_1_shdw(timings, min_tck, | ||
1385 | addressing); | ||
1386 | regs->sdram_tim2_shdw = get_sdram_tim_2_shdw(timings, min_tck, | ||
1387 | addressing, type); | ||
1388 | regs->sdram_tim3_shdw = get_sdram_tim_3_shdw(timings, min_tck, | ||
1389 | addressing, type, ip_rev, EMIF_NORMAL_TIMINGS); | ||
1390 | |||
1391 | cl = get_cl(emif); | ||
1392 | |||
1393 | if (phy_type == EMIF_PHY_TYPE_ATTILAPHY && ip_rev == EMIF_4D) { | ||
1394 | regs->phy_ctrl_1_shdw = get_ddr_phy_ctrl_1_attilaphy_4d( | ||
1395 | timings, freq, cl); | ||
1396 | } else if (phy_type == EMIF_PHY_TYPE_INTELLIPHY && ip_rev == EMIF_4D5) { | ||
1397 | regs->phy_ctrl_1_shdw = get_phy_ctrl_1_intelliphy_4d5(freq, cl); | ||
1398 | regs->ext_phy_ctrl_2_shdw = get_ext_phy_ctrl_2_intelliphy_4d5(); | ||
1399 | regs->ext_phy_ctrl_3_shdw = get_ext_phy_ctrl_3_intelliphy_4d5(); | ||
1400 | regs->ext_phy_ctrl_4_shdw = get_ext_phy_ctrl_4_intelliphy_4d5(); | ||
1401 | } else { | ||
1402 | return -1; | ||
1403 | } | ||
1404 | |||
1405 | /* Only timeout values in pwr_mgmt_ctrl_shdw register */ | ||
1406 | regs->pwr_mgmt_ctrl_shdw = | ||
1407 | get_pwr_mgmt_ctrl(freq, emif_for_calc, ip_rev) & | ||
1408 | (CS_TIM_MASK | SR_TIM_MASK | PD_TIM_MASK); | ||
1409 | |||
1410 | if (ip_rev & EMIF_4D) { | ||
1411 | regs->read_idle_ctrl_shdw_normal = | ||
1412 | get_read_idle_ctrl_shdw(DDR_VOLTAGE_STABLE); | ||
1413 | |||
1414 | regs->read_idle_ctrl_shdw_volt_ramp = | ||
1415 | get_read_idle_ctrl_shdw(DDR_VOLTAGE_RAMPING); | ||
1416 | } else if (ip_rev & EMIF_4D5) { | ||
1417 | regs->dll_calib_ctrl_shdw_normal = | ||
1418 | get_dll_calib_ctrl_shdw(DDR_VOLTAGE_STABLE); | ||
1419 | |||
1420 | regs->dll_calib_ctrl_shdw_volt_ramp = | ||
1421 | get_dll_calib_ctrl_shdw(DDR_VOLTAGE_RAMPING); | ||
1422 | } | ||
1423 | |||
1424 | if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { | ||
1425 | regs->ref_ctrl_shdw_derated = get_sdram_ref_ctrl_shdw(freq / 4, | ||
1426 | addressing); | ||
1427 | |||
1428 | regs->sdram_tim1_shdw_derated = | ||
1429 | get_sdram_tim_1_shdw_derated(timings, min_tck, | ||
1430 | addressing); | ||
1431 | |||
1432 | regs->sdram_tim3_shdw_derated = get_sdram_tim_3_shdw(timings, | ||
1433 | min_tck, addressing, type, ip_rev, | ||
1434 | EMIF_DERATED_TIMINGS); | ||
1435 | } | ||
1436 | |||
1437 | regs->freq = freq; | ||
1438 | |||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | /* | ||
1443 | * get_regs() - gets the cached emif_regs structure for a given EMIF instance | ||
1444 | * given frequency(freq): | ||
1445 | * | ||
1446 | * As an optimisation, every EMIF instance other than EMIF1 shares the | ||
1447 | * register cache with EMIF1 if the devices connected on this instance | ||
1448 | * are same as that on EMIF1(indicated by the duplicate flag) | ||
1449 | * | ||
1450 | * If we do not have an entry corresponding to the frequency given, we | ||
1451 | * allocate a new entry and calculate the values | ||
1452 | * | ||
1453 | * Upon finding the right reg dump, save it in curr_regs. It can be | ||
1454 | * directly used for thermal de-rating and voltage ramping changes. | ||
1455 | */ | ||
1456 | static struct emif_regs *get_regs(struct emif_data *emif, u32 freq) | ||
1457 | { | ||
1458 | int i; | ||
1459 | struct emif_regs **regs_cache; | ||
1460 | struct emif_regs *regs = NULL; | ||
1461 | struct device *dev; | ||
1462 | |||
1463 | dev = emif->dev; | ||
1464 | if (emif->curr_regs && emif->curr_regs->freq == freq) { | ||
1465 | dev_dbg(dev, "%s: using curr_regs - %u Hz", __func__, freq); | ||
1466 | return emif->curr_regs; | ||
1467 | } | ||
1468 | |||
1469 | if (emif->duplicate) | ||
1470 | regs_cache = emif1->regs_cache; | ||
1471 | else | ||
1472 | regs_cache = emif->regs_cache; | ||
1473 | |||
1474 | for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) { | ||
1475 | if (regs_cache[i]->freq == freq) { | ||
1476 | regs = regs_cache[i]; | ||
1477 | dev_dbg(dev, | ||
1478 | "%s: reg dump found in reg cache for %u Hz\n", | ||
1479 | __func__, freq); | ||
1480 | break; | ||
1481 | } | ||
1482 | } | ||
1483 | |||
1484 | /* | ||
1485 | * If we don't have an entry for this frequency in the cache create one | ||
1486 | * and calculate the values | ||
1487 | */ | ||
1488 | if (!regs) { | ||
1489 | regs = devm_kzalloc(emif->dev, sizeof(*regs), GFP_ATOMIC); | ||
1490 | if (!regs) | ||
1491 | return NULL; | ||
1492 | |||
1493 | if (get_emif_reg_values(emif, freq, regs)) { | ||
1494 | devm_kfree(emif->dev, regs); | ||
1495 | return NULL; | ||
1496 | } | ||
1497 | |||
1498 | /* | ||
1499 | * Now look for an un-used entry in the cache and save the | ||
1500 | * newly created struct. If there are no free entries | ||
1501 | * over-write the last entry | ||
1502 | */ | ||
1503 | for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) | ||
1504 | ; | ||
1505 | |||
1506 | if (i >= EMIF_MAX_NUM_FREQUENCIES) { | ||
1507 | dev_warn(dev, "%s: regs_cache full - reusing a slot!!\n", | ||
1508 | __func__); | ||
1509 | i = EMIF_MAX_NUM_FREQUENCIES - 1; | ||
1510 | devm_kfree(emif->dev, regs_cache[i]); | ||
1511 | } | ||
1512 | regs_cache[i] = regs; | ||
1513 | } | ||
1514 | |||
1515 | return regs; | ||
1516 | } | ||
1517 | |||
1518 | static void do_volt_notify_handling(struct emif_data *emif, u32 volt_state) | ||
1519 | { | ||
1520 | dev_dbg(emif->dev, "%s: voltage notification : %d", __func__, | ||
1521 | volt_state); | ||
1522 | |||
1523 | if (!emif->curr_regs) { | ||
1524 | dev_err(emif->dev, | ||
1525 | "%s: volt-notify before registers are ready: %d\n", | ||
1526 | __func__, volt_state); | ||
1527 | return; | ||
1528 | } | ||
1529 | |||
1530 | setup_volt_sensitive_regs(emif, emif->curr_regs, volt_state); | ||
1531 | } | ||
1532 | |||
1533 | /* | ||
1534 | * TODO: voltage notify handling should be hooked up to | ||
1535 | * regulator framework as soon as the necessary support | ||
1536 | * is available in mainline kernel. This function is un-used | ||
1537 | * right now. | ||
1538 | */ | ||
1539 | static void __attribute__((unused)) volt_notify_handling(u32 volt_state) | ||
1540 | { | ||
1541 | struct emif_data *emif; | ||
1542 | |||
1543 | spin_lock_irqsave(&emif_lock, irq_state); | ||
1544 | |||
1545 | list_for_each_entry(emif, &device_list, node) | ||
1546 | do_volt_notify_handling(emif, volt_state); | ||
1547 | do_freq_update(); | ||
1548 | |||
1549 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
1550 | } | ||
1551 | |||
1552 | static void do_freq_pre_notify_handling(struct emif_data *emif, u32 new_freq) | ||
1553 | { | ||
1554 | struct emif_regs *regs; | ||
1555 | |||
1556 | regs = get_regs(emif, new_freq); | ||
1557 | if (!regs) | ||
1558 | return; | ||
1559 | |||
1560 | emif->curr_regs = regs; | ||
1561 | |||
1562 | /* | ||
1563 | * Update the shadow registers: | ||
1564 | * Temperature and voltage-ramp sensitive settings are also configured | ||
1565 | * in terms of DDR cycles. So, we need to update them too when there | ||
1566 | * is a freq change | ||
1567 | */ | ||
1568 | dev_dbg(emif->dev, "%s: setting up shadow registers for %uHz", | ||
1569 | __func__, new_freq); | ||
1570 | setup_registers(emif, regs); | ||
1571 | setup_temperature_sensitive_regs(emif, regs); | ||
1572 | setup_volt_sensitive_regs(emif, regs, DDR_VOLTAGE_STABLE); | ||
1573 | |||
1574 | /* | ||
1575 | * Part of workaround for errata i728. See do_freq_update() | ||
1576 | * for more details | ||
1577 | */ | ||
1578 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
1579 | set_lpmode(emif, EMIF_LP_MODE_DISABLE); | ||
1580 | } | ||
1581 | |||
1582 | /* | ||
1583 | * TODO: frequency notify handling should be hooked up to | ||
1584 | * clock framework as soon as the necessary support is | ||
1585 | * available in mainline kernel. This function is un-used | ||
1586 | * right now. | ||
1587 | */ | ||
1588 | static void __attribute__((unused)) freq_pre_notify_handling(u32 new_freq) | ||
1589 | { | ||
1590 | struct emif_data *emif; | ||
1591 | |||
1592 | /* | ||
1593 | * NOTE: we are taking the spin-lock here and releases it | ||
1594 | * only in post-notifier. This doesn't look good and | ||
1595 | * Sparse complains about it, but this seems to be | ||
1596 | * un-avoidable. We need to lock a sequence of events | ||
1597 | * that is split between EMIF and clock framework. | ||
1598 | * | ||
1599 | * 1. EMIF driver updates EMIF timings in shadow registers in the | ||
1600 | * frequency pre-notify callback from clock framework | ||
1601 | * 2. clock framework sets up the registers for the new frequency | ||
1602 | * 3. clock framework initiates a hw-sequence that updates | ||
1603 | * the frequency EMIF timings synchronously. | ||
1604 | * | ||
1605 | * All these 3 steps should be performed as an atomic operation | ||
1606 | * vis-a-vis similar sequence in the EMIF interrupt handler | ||
1607 | * for temperature events. Otherwise, there could be race | ||
1608 | * conditions that could result in incorrect EMIF timings for | ||
1609 | * a given frequency | ||
1610 | */ | ||
1611 | spin_lock_irqsave(&emif_lock, irq_state); | ||
1612 | |||
1613 | list_for_each_entry(emif, &device_list, node) | ||
1614 | do_freq_pre_notify_handling(emif, new_freq); | ||
1615 | } | ||
1616 | |||
1617 | static void do_freq_post_notify_handling(struct emif_data *emif) | ||
1618 | { | ||
1619 | /* | ||
1620 | * Part of workaround for errata i728. See do_freq_update() | ||
1621 | * for more details | ||
1622 | */ | ||
1623 | if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH) | ||
1624 | set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH); | ||
1625 | } | ||
1626 | |||
1627 | /* | ||
1628 | * TODO: frequency notify handling should be hooked up to | ||
1629 | * clock framework as soon as the necessary support is | ||
1630 | * available in mainline kernel. This function is un-used | ||
1631 | * right now. | ||
1632 | */ | ||
1633 | static void __attribute__((unused)) freq_post_notify_handling(void) | ||
1634 | { | ||
1635 | struct emif_data *emif; | ||
1636 | |||
1637 | list_for_each_entry(emif, &device_list, node) | ||
1638 | do_freq_post_notify_handling(emif); | ||
1639 | |||
1640 | /* | ||
1641 | * Lock is done in pre-notify handler. See freq_pre_notify_handling() | ||
1642 | * for more details | ||
1643 | */ | ||
1644 | spin_unlock_irqrestore(&emif_lock, irq_state); | ||
1645 | } | ||
1646 | |||
1647 | static struct platform_driver emif_driver = { | ||
1648 | .remove = __exit_p(emif_remove), | ||
1649 | .shutdown = emif_shutdown, | ||
1650 | .driver = { | ||
1651 | .name = "emif", | ||
1652 | }, | ||
1653 | }; | ||
1654 | |||
1655 | static int __init_or_module emif_register(void) | ||
1656 | { | ||
1657 | return platform_driver_probe(&emif_driver, emif_probe); | ||
1658 | } | ||
1659 | |||
1660 | static void __exit emif_unregister(void) | ||
1661 | { | ||
1662 | platform_driver_unregister(&emif_driver); | ||
1663 | } | ||
1664 | |||
1665 | module_init(emif_register); | ||
1666 | module_exit(emif_unregister); | ||
1667 | MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver"); | ||
1668 | MODULE_LICENSE("GPL"); | ||
1669 | MODULE_ALIAS("platform:emif"); | ||
1670 | MODULE_AUTHOR("Texas Instruments Inc"); | ||
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h new file mode 100644 index 000000000000..bfe08bae961a --- /dev/null +++ b/drivers/memory/emif.h | |||
@@ -0,0 +1,589 @@ | |||
1 | /* | ||
2 | * Defines for the EMIF driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Benoit Cousson (b-cousson@ti.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef __EMIF_H | ||
13 | #define __EMIF_H | ||
14 | |||
15 | /* | ||
16 | * Maximum number of different frequencies supported by EMIF driver | ||
17 | * Determines the number of entries in the pointer array for register | ||
18 | * cache | ||
19 | */ | ||
20 | #define EMIF_MAX_NUM_FREQUENCIES 6 | ||
21 | |||
22 | /* State of the core voltage */ | ||
23 | #define DDR_VOLTAGE_STABLE 0 | ||
24 | #define DDR_VOLTAGE_RAMPING 1 | ||
25 | |||
26 | /* Defines for timing De-rating */ | ||
27 | #define EMIF_NORMAL_TIMINGS 0 | ||
28 | #define EMIF_DERATED_TIMINGS 1 | ||
29 | |||
30 | /* Length of the forced read idle period in terms of cycles */ | ||
31 | #define EMIF_READ_IDLE_LEN_VAL 5 | ||
32 | |||
33 | /* | ||
34 | * forced read idle interval to be used when voltage | ||
35 | * is changed as part of DVFS/DPS - 1ms | ||
36 | */ | ||
37 | #define READ_IDLE_INTERVAL_DVFS (1*1000000) | ||
38 | |||
39 | /* | ||
40 | * Forced read idle interval to be used when voltage is stable | ||
41 | * 50us - or maximum value will do | ||
42 | */ | ||
43 | #define READ_IDLE_INTERVAL_NORMAL (50*1000000) | ||
44 | |||
45 | /* DLL calibration interval when voltage is NOT stable - 1us */ | ||
46 | #define DLL_CALIB_INTERVAL_DVFS (1*1000000) | ||
47 | |||
48 | #define DLL_CALIB_ACK_WAIT_VAL 5 | ||
49 | |||
50 | /* Interval between ZQCS commands - hw team recommended value */ | ||
51 | #define EMIF_ZQCS_INTERVAL_US (50*1000) | ||
52 | /* Enable ZQ Calibration on exiting Self-refresh */ | ||
53 | #define ZQ_SFEXITEN_ENABLE 1 | ||
54 | /* | ||
55 | * ZQ Calibration simultaneously on both chip-selects: | ||
56 | * Needs one calibration resistor per CS | ||
57 | */ | ||
58 | #define ZQ_DUALCALEN_DISABLE 0 | ||
59 | #define ZQ_DUALCALEN_ENABLE 1 | ||
60 | |||
61 | #define T_ZQCS_DEFAULT_NS 90 | ||
62 | #define T_ZQCL_DEFAULT_NS 360 | ||
63 | #define T_ZQINIT_DEFAULT_NS 1000 | ||
64 | |||
65 | /* DPD_EN */ | ||
66 | #define DPD_DISABLE 0 | ||
67 | #define DPD_ENABLE 1 | ||
68 | |||
69 | /* | ||
70 | * Default values for the low-power entry to be used if not provided by user. | ||
71 | * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512 | ||
72 | * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz | ||
73 | */ | ||
74 | #define EMIF_LP_MODE_TIMEOUT_PERFORMANCE 2048 | ||
75 | #define EMIF_LP_MODE_TIMEOUT_POWER 512 | ||
76 | #define EMIF_LP_MODE_FREQ_THRESHOLD 400000000 | ||
77 | |||
78 | /* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */ | ||
79 | #define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY 0x049FF000 | ||
80 | #define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY 0x41 | ||
81 | #define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY 0x80 | ||
82 | #define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF | ||
83 | |||
84 | /* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */ | ||
85 | #define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY 0x0E084200 | ||
86 | #define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS 10000 | ||
87 | |||
88 | /* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */ | ||
89 | #define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS 360 | ||
90 | |||
91 | #define EMIF_T_CSTA 3 | ||
92 | #define EMIF_T_PDLL_UL 128 | ||
93 | |||
94 | /* External PHY control registers magic values */ | ||
95 | #define EMIF_EXT_PHY_CTRL_1_VAL 0x04020080 | ||
96 | #define EMIF_EXT_PHY_CTRL_5_VAL 0x04010040 | ||
97 | #define EMIF_EXT_PHY_CTRL_6_VAL 0x01004010 | ||
98 | #define EMIF_EXT_PHY_CTRL_7_VAL 0x00001004 | ||
99 | #define EMIF_EXT_PHY_CTRL_8_VAL 0x04010040 | ||
100 | #define EMIF_EXT_PHY_CTRL_9_VAL 0x01004010 | ||
101 | #define EMIF_EXT_PHY_CTRL_10_VAL 0x00001004 | ||
102 | #define EMIF_EXT_PHY_CTRL_11_VAL 0x00000000 | ||
103 | #define EMIF_EXT_PHY_CTRL_12_VAL 0x00000000 | ||
104 | #define EMIF_EXT_PHY_CTRL_13_VAL 0x00000000 | ||
105 | #define EMIF_EXT_PHY_CTRL_14_VAL 0x80080080 | ||
106 | #define EMIF_EXT_PHY_CTRL_15_VAL 0x00800800 | ||
107 | #define EMIF_EXT_PHY_CTRL_16_VAL 0x08102040 | ||
108 | #define EMIF_EXT_PHY_CTRL_17_VAL 0x00000001 | ||
109 | #define EMIF_EXT_PHY_CTRL_18_VAL 0x540A8150 | ||
110 | #define EMIF_EXT_PHY_CTRL_19_VAL 0xA81502A0 | ||
111 | #define EMIF_EXT_PHY_CTRL_20_VAL 0x002A0540 | ||
112 | #define EMIF_EXT_PHY_CTRL_21_VAL 0x00000000 | ||
113 | #define EMIF_EXT_PHY_CTRL_22_VAL 0x00000000 | ||
114 | #define EMIF_EXT_PHY_CTRL_23_VAL 0x00000000 | ||
115 | #define EMIF_EXT_PHY_CTRL_24_VAL 0x00000077 | ||
116 | |||
117 | #define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS 1200 | ||
118 | |||
119 | /* Registers offset */ | ||
120 | #define EMIF_MODULE_ID_AND_REVISION 0x0000 | ||
121 | #define EMIF_STATUS 0x0004 | ||
122 | #define EMIF_SDRAM_CONFIG 0x0008 | ||
123 | #define EMIF_SDRAM_CONFIG_2 0x000c | ||
124 | #define EMIF_SDRAM_REFRESH_CONTROL 0x0010 | ||
125 | #define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 | ||
126 | #define EMIF_SDRAM_TIMING_1 0x0018 | ||
127 | #define EMIF_SDRAM_TIMING_1_SHDW 0x001c | ||
128 | #define EMIF_SDRAM_TIMING_2 0x0020 | ||
129 | #define EMIF_SDRAM_TIMING_2_SHDW 0x0024 | ||
130 | #define EMIF_SDRAM_TIMING_3 0x0028 | ||
131 | #define EMIF_SDRAM_TIMING_3_SHDW 0x002c | ||
132 | #define EMIF_LPDDR2_NVM_TIMING 0x0030 | ||
133 | #define EMIF_LPDDR2_NVM_TIMING_SHDW 0x0034 | ||
134 | #define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 | ||
135 | #define EMIF_POWER_MANAGEMENT_CTRL_SHDW 0x003c | ||
136 | #define EMIF_LPDDR2_MODE_REG_DATA 0x0040 | ||
137 | #define EMIF_LPDDR2_MODE_REG_CONFIG 0x0050 | ||
138 | #define EMIF_OCP_CONFIG 0x0054 | ||
139 | #define EMIF_OCP_CONFIG_VALUE_1 0x0058 | ||
140 | #define EMIF_OCP_CONFIG_VALUE_2 0x005c | ||
141 | #define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 | ||
142 | #define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 | ||
143 | #define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 | ||
144 | #define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c | ||
145 | #define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 | ||
146 | #define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 | ||
147 | #define EMIF_PERFORMANCE_COUNTER_1 0x0080 | ||
148 | #define EMIF_PERFORMANCE_COUNTER_2 0x0084 | ||
149 | #define EMIF_PERFORMANCE_COUNTER_CONFIG 0x0088 | ||
150 | #define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c | ||
151 | #define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 | ||
152 | #define EMIF_MISC_REG 0x0094 | ||
153 | #define EMIF_DLL_CALIB_CTRL 0x0098 | ||
154 | #define EMIF_DLL_CALIB_CTRL_SHDW 0x009c | ||
155 | #define EMIF_END_OF_INTERRUPT 0x00a0 | ||
156 | #define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 | ||
157 | #define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 | ||
158 | #define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac | ||
159 | #define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 | ||
160 | #define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 | ||
161 | #define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 | ||
162 | #define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc | ||
163 | #define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 | ||
164 | #define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 | ||
165 | #define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc | ||
166 | #define EMIF_OCP_ERROR_LOG 0x00d0 | ||
167 | #define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 | ||
168 | #define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 | ||
169 | #define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc | ||
170 | #define EMIF_DDR_PHY_CTRL_1 0x00e4 | ||
171 | #define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 | ||
172 | #define EMIF_DDR_PHY_CTRL_2 0x00ec | ||
173 | #define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100 | ||
174 | #define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104 | ||
175 | #define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108 | ||
176 | #define EMIF_READ_WRITE_EXECUTION_THRESHOLD 0x0120 | ||
177 | #define EMIF_COS_CONFIG 0x0124 | ||
178 | #define EMIF_PHY_STATUS_1 0x0140 | ||
179 | #define EMIF_PHY_STATUS_2 0x0144 | ||
180 | #define EMIF_PHY_STATUS_3 0x0148 | ||
181 | #define EMIF_PHY_STATUS_4 0x014c | ||
182 | #define EMIF_PHY_STATUS_5 0x0150 | ||
183 | #define EMIF_PHY_STATUS_6 0x0154 | ||
184 | #define EMIF_PHY_STATUS_7 0x0158 | ||
185 | #define EMIF_PHY_STATUS_8 0x015c | ||
186 | #define EMIF_PHY_STATUS_9 0x0160 | ||
187 | #define EMIF_PHY_STATUS_10 0x0164 | ||
188 | #define EMIF_PHY_STATUS_11 0x0168 | ||
189 | #define EMIF_PHY_STATUS_12 0x016c | ||
190 | #define EMIF_PHY_STATUS_13 0x0170 | ||
191 | #define EMIF_PHY_STATUS_14 0x0174 | ||
192 | #define EMIF_PHY_STATUS_15 0x0178 | ||
193 | #define EMIF_PHY_STATUS_16 0x017c | ||
194 | #define EMIF_PHY_STATUS_17 0x0180 | ||
195 | #define EMIF_PHY_STATUS_18 0x0184 | ||
196 | #define EMIF_PHY_STATUS_19 0x0188 | ||
197 | #define EMIF_PHY_STATUS_20 0x018c | ||
198 | #define EMIF_PHY_STATUS_21 0x0190 | ||
199 | #define EMIF_EXT_PHY_CTRL_1 0x0200 | ||
200 | #define EMIF_EXT_PHY_CTRL_1_SHDW 0x0204 | ||
201 | #define EMIF_EXT_PHY_CTRL_2 0x0208 | ||
202 | #define EMIF_EXT_PHY_CTRL_2_SHDW 0x020c | ||
203 | #define EMIF_EXT_PHY_CTRL_3 0x0210 | ||
204 | #define EMIF_EXT_PHY_CTRL_3_SHDW 0x0214 | ||
205 | #define EMIF_EXT_PHY_CTRL_4 0x0218 | ||
206 | #define EMIF_EXT_PHY_CTRL_4_SHDW 0x021c | ||
207 | #define EMIF_EXT_PHY_CTRL_5 0x0220 | ||
208 | #define EMIF_EXT_PHY_CTRL_5_SHDW 0x0224 | ||
209 | #define EMIF_EXT_PHY_CTRL_6 0x0228 | ||
210 | #define EMIF_EXT_PHY_CTRL_6_SHDW 0x022c | ||
211 | #define EMIF_EXT_PHY_CTRL_7 0x0230 | ||
212 | #define EMIF_EXT_PHY_CTRL_7_SHDW 0x0234 | ||
213 | #define EMIF_EXT_PHY_CTRL_8 0x0238 | ||
214 | #define EMIF_EXT_PHY_CTRL_8_SHDW 0x023c | ||
215 | #define EMIF_EXT_PHY_CTRL_9 0x0240 | ||
216 | #define EMIF_EXT_PHY_CTRL_9_SHDW 0x0244 | ||
217 | #define EMIF_EXT_PHY_CTRL_10 0x0248 | ||
218 | #define EMIF_EXT_PHY_CTRL_10_SHDW 0x024c | ||
219 | #define EMIF_EXT_PHY_CTRL_11 0x0250 | ||
220 | #define EMIF_EXT_PHY_CTRL_11_SHDW 0x0254 | ||
221 | #define EMIF_EXT_PHY_CTRL_12 0x0258 | ||
222 | #define EMIF_EXT_PHY_CTRL_12_SHDW 0x025c | ||
223 | #define EMIF_EXT_PHY_CTRL_13 0x0260 | ||
224 | #define EMIF_EXT_PHY_CTRL_13_SHDW 0x0264 | ||
225 | #define EMIF_EXT_PHY_CTRL_14 0x0268 | ||
226 | #define EMIF_EXT_PHY_CTRL_14_SHDW 0x026c | ||
227 | #define EMIF_EXT_PHY_CTRL_15 0x0270 | ||
228 | #define EMIF_EXT_PHY_CTRL_15_SHDW 0x0274 | ||
229 | #define EMIF_EXT_PHY_CTRL_16 0x0278 | ||
230 | #define EMIF_EXT_PHY_CTRL_16_SHDW 0x027c | ||
231 | #define EMIF_EXT_PHY_CTRL_17 0x0280 | ||
232 | #define EMIF_EXT_PHY_CTRL_17_SHDW 0x0284 | ||
233 | #define EMIF_EXT_PHY_CTRL_18 0x0288 | ||
234 | #define EMIF_EXT_PHY_CTRL_18_SHDW 0x028c | ||
235 | #define EMIF_EXT_PHY_CTRL_19 0x0290 | ||
236 | #define EMIF_EXT_PHY_CTRL_19_SHDW 0x0294 | ||
237 | #define EMIF_EXT_PHY_CTRL_20 0x0298 | ||
238 | #define EMIF_EXT_PHY_CTRL_20_SHDW 0x029c | ||
239 | #define EMIF_EXT_PHY_CTRL_21 0x02a0 | ||
240 | #define EMIF_EXT_PHY_CTRL_21_SHDW 0x02a4 | ||
241 | #define EMIF_EXT_PHY_CTRL_22 0x02a8 | ||
242 | #define EMIF_EXT_PHY_CTRL_22_SHDW 0x02ac | ||
243 | #define EMIF_EXT_PHY_CTRL_23 0x02b0 | ||
244 | #define EMIF_EXT_PHY_CTRL_23_SHDW 0x02b4 | ||
245 | #define EMIF_EXT_PHY_CTRL_24 0x02b8 | ||
246 | #define EMIF_EXT_PHY_CTRL_24_SHDW 0x02bc | ||
247 | #define EMIF_EXT_PHY_CTRL_25 0x02c0 | ||
248 | #define EMIF_EXT_PHY_CTRL_25_SHDW 0x02c4 | ||
249 | #define EMIF_EXT_PHY_CTRL_26 0x02c8 | ||
250 | #define EMIF_EXT_PHY_CTRL_26_SHDW 0x02cc | ||
251 | #define EMIF_EXT_PHY_CTRL_27 0x02d0 | ||
252 | #define EMIF_EXT_PHY_CTRL_27_SHDW 0x02d4 | ||
253 | #define EMIF_EXT_PHY_CTRL_28 0x02d8 | ||
254 | #define EMIF_EXT_PHY_CTRL_28_SHDW 0x02dc | ||
255 | #define EMIF_EXT_PHY_CTRL_29 0x02e0 | ||
256 | #define EMIF_EXT_PHY_CTRL_29_SHDW 0x02e4 | ||
257 | #define EMIF_EXT_PHY_CTRL_30 0x02e8 | ||
258 | #define EMIF_EXT_PHY_CTRL_30_SHDW 0x02ec | ||
259 | |||
260 | /* Registers shifts and masks */ | ||
261 | |||
262 | /* EMIF_MODULE_ID_AND_REVISION */ | ||
263 | #define SCHEME_SHIFT 30 | ||
264 | #define SCHEME_MASK (0x3 << 30) | ||
265 | #define MODULE_ID_SHIFT 16 | ||
266 | #define MODULE_ID_MASK (0xfff << 16) | ||
267 | #define RTL_VERSION_SHIFT 11 | ||
268 | #define RTL_VERSION_MASK (0x1f << 11) | ||
269 | #define MAJOR_REVISION_SHIFT 8 | ||
270 | #define MAJOR_REVISION_MASK (0x7 << 8) | ||
271 | #define MINOR_REVISION_SHIFT 0 | ||
272 | #define MINOR_REVISION_MASK (0x3f << 0) | ||
273 | |||
274 | /* STATUS */ | ||
275 | #define BE_SHIFT 31 | ||
276 | #define BE_MASK (1 << 31) | ||
277 | #define DUAL_CLK_MODE_SHIFT 30 | ||
278 | #define DUAL_CLK_MODE_MASK (1 << 30) | ||
279 | #define FAST_INIT_SHIFT 29 | ||
280 | #define FAST_INIT_MASK (1 << 29) | ||
281 | #define RDLVLGATETO_SHIFT 6 | ||
282 | #define RDLVLGATETO_MASK (1 << 6) | ||
283 | #define RDLVLTO_SHIFT 5 | ||
284 | #define RDLVLTO_MASK (1 << 5) | ||
285 | #define WRLVLTO_SHIFT 4 | ||
286 | #define WRLVLTO_MASK (1 << 4) | ||
287 | #define PHY_DLL_READY_SHIFT 2 | ||
288 | #define PHY_DLL_READY_MASK (1 << 2) | ||
289 | |||
290 | /* SDRAM_CONFIG */ | ||
291 | #define SDRAM_TYPE_SHIFT 29 | ||
292 | #define SDRAM_TYPE_MASK (0x7 << 29) | ||
293 | #define IBANK_POS_SHIFT 27 | ||
294 | #define IBANK_POS_MASK (0x3 << 27) | ||
295 | #define DDR_TERM_SHIFT 24 | ||
296 | #define DDR_TERM_MASK (0x7 << 24) | ||
297 | #define DDR2_DDQS_SHIFT 23 | ||
298 | #define DDR2_DDQS_MASK (1 << 23) | ||
299 | #define DYN_ODT_SHIFT 21 | ||
300 | #define DYN_ODT_MASK (0x3 << 21) | ||
301 | #define DDR_DISABLE_DLL_SHIFT 20 | ||
302 | #define DDR_DISABLE_DLL_MASK (1 << 20) | ||
303 | #define SDRAM_DRIVE_SHIFT 18 | ||
304 | #define SDRAM_DRIVE_MASK (0x3 << 18) | ||
305 | #define CWL_SHIFT 16 | ||
306 | #define CWL_MASK (0x3 << 16) | ||
307 | #define NARROW_MODE_SHIFT 14 | ||
308 | #define NARROW_MODE_MASK (0x3 << 14) | ||
309 | #define CL_SHIFT 10 | ||
310 | #define CL_MASK (0xf << 10) | ||
311 | #define ROWSIZE_SHIFT 7 | ||
312 | #define ROWSIZE_MASK (0x7 << 7) | ||
313 | #define IBANK_SHIFT 4 | ||
314 | #define IBANK_MASK (0x7 << 4) | ||
315 | #define EBANK_SHIFT 3 | ||
316 | #define EBANK_MASK (1 << 3) | ||
317 | #define PAGESIZE_SHIFT 0 | ||
318 | #define PAGESIZE_MASK (0x7 << 0) | ||
319 | |||
320 | /* SDRAM_CONFIG_2 */ | ||
321 | #define CS1NVMEN_SHIFT 30 | ||
322 | #define CS1NVMEN_MASK (1 << 30) | ||
323 | #define EBANK_POS_SHIFT 27 | ||
324 | #define EBANK_POS_MASK (1 << 27) | ||
325 | #define RDBNUM_SHIFT 4 | ||
326 | #define RDBNUM_MASK (0x3 << 4) | ||
327 | #define RDBSIZE_SHIFT 0 | ||
328 | #define RDBSIZE_MASK (0x7 << 0) | ||
329 | |||
330 | /* SDRAM_REFRESH_CONTROL */ | ||
331 | #define INITREF_DIS_SHIFT 31 | ||
332 | #define INITREF_DIS_MASK (1 << 31) | ||
333 | #define SRT_SHIFT 29 | ||
334 | #define SRT_MASK (1 << 29) | ||
335 | #define ASR_SHIFT 28 | ||
336 | #define ASR_MASK (1 << 28) | ||
337 | #define PASR_SHIFT 24 | ||
338 | #define PASR_MASK (0x7 << 24) | ||
339 | #define REFRESH_RATE_SHIFT 0 | ||
340 | #define REFRESH_RATE_MASK (0xffff << 0) | ||
341 | |||
342 | /* SDRAM_TIMING_1 */ | ||
343 | #define T_RTW_SHIFT 29 | ||
344 | #define T_RTW_MASK (0x7 << 29) | ||
345 | #define T_RP_SHIFT 25 | ||
346 | #define T_RP_MASK (0xf << 25) | ||
347 | #define T_RCD_SHIFT 21 | ||
348 | #define T_RCD_MASK (0xf << 21) | ||
349 | #define T_WR_SHIFT 17 | ||
350 | #define T_WR_MASK (0xf << 17) | ||
351 | #define T_RAS_SHIFT 12 | ||
352 | #define T_RAS_MASK (0x1f << 12) | ||
353 | #define T_RC_SHIFT 6 | ||
354 | #define T_RC_MASK (0x3f << 6) | ||
355 | #define T_RRD_SHIFT 3 | ||
356 | #define T_RRD_MASK (0x7 << 3) | ||
357 | #define T_WTR_SHIFT 0 | ||
358 | #define T_WTR_MASK (0x7 << 0) | ||
359 | |||
360 | /* SDRAM_TIMING_2 */ | ||
361 | #define T_XP_SHIFT 28 | ||
362 | #define T_XP_MASK (0x7 << 28) | ||
363 | #define T_ODT_SHIFT 25 | ||
364 | #define T_ODT_MASK (0x7 << 25) | ||
365 | #define T_XSNR_SHIFT 16 | ||
366 | #define T_XSNR_MASK (0x1ff << 16) | ||
367 | #define T_XSRD_SHIFT 6 | ||
368 | #define T_XSRD_MASK (0x3ff << 6) | ||
369 | #define T_RTP_SHIFT 3 | ||
370 | #define T_RTP_MASK (0x7 << 3) | ||
371 | #define T_CKE_SHIFT 0 | ||
372 | #define T_CKE_MASK (0x7 << 0) | ||
373 | |||
374 | /* SDRAM_TIMING_3 */ | ||
375 | #define T_PDLL_UL_SHIFT 28 | ||
376 | #define T_PDLL_UL_MASK (0xf << 28) | ||
377 | #define T_CSTA_SHIFT 24 | ||
378 | #define T_CSTA_MASK (0xf << 24) | ||
379 | #define T_CKESR_SHIFT 21 | ||
380 | #define T_CKESR_MASK (0x7 << 21) | ||
381 | #define ZQ_ZQCS_SHIFT 15 | ||
382 | #define ZQ_ZQCS_MASK (0x3f << 15) | ||
383 | #define T_TDQSCKMAX_SHIFT 13 | ||
384 | #define T_TDQSCKMAX_MASK (0x3 << 13) | ||
385 | #define T_RFC_SHIFT 4 | ||
386 | #define T_RFC_MASK (0x1ff << 4) | ||
387 | #define T_RAS_MAX_SHIFT 0 | ||
388 | #define T_RAS_MAX_MASK (0xf << 0) | ||
389 | |||
390 | /* POWER_MANAGEMENT_CONTROL */ | ||
391 | #define PD_TIM_SHIFT 12 | ||
392 | #define PD_TIM_MASK (0xf << 12) | ||
393 | #define DPD_EN_SHIFT 11 | ||
394 | #define DPD_EN_MASK (1 << 11) | ||
395 | #define LP_MODE_SHIFT 8 | ||
396 | #define LP_MODE_MASK (0x7 << 8) | ||
397 | #define SR_TIM_SHIFT 4 | ||
398 | #define SR_TIM_MASK (0xf << 4) | ||
399 | #define CS_TIM_SHIFT 0 | ||
400 | #define CS_TIM_MASK (0xf << 0) | ||
401 | |||
402 | /* LPDDR2_MODE_REG_DATA */ | ||
403 | #define VALUE_0_SHIFT 0 | ||
404 | #define VALUE_0_MASK (0x7f << 0) | ||
405 | |||
406 | /* LPDDR2_MODE_REG_CONFIG */ | ||
407 | #define CS_SHIFT 31 | ||
408 | #define CS_MASK (1 << 31) | ||
409 | #define REFRESH_EN_SHIFT 30 | ||
410 | #define REFRESH_EN_MASK (1 << 30) | ||
411 | #define ADDRESS_SHIFT 0 | ||
412 | #define ADDRESS_MASK (0xff << 0) | ||
413 | |||
414 | /* OCP_CONFIG */ | ||
415 | #define SYS_THRESH_MAX_SHIFT 24 | ||
416 | #define SYS_THRESH_MAX_MASK (0xf << 24) | ||
417 | #define MPU_THRESH_MAX_SHIFT 20 | ||
418 | #define MPU_THRESH_MAX_MASK (0xf << 20) | ||
419 | #define LL_THRESH_MAX_SHIFT 16 | ||
420 | #define LL_THRESH_MAX_MASK (0xf << 16) | ||
421 | |||
422 | /* PERFORMANCE_COUNTER_1 */ | ||
423 | #define COUNTER1_SHIFT 0 | ||
424 | #define COUNTER1_MASK (0xffffffff << 0) | ||
425 | |||
426 | /* PERFORMANCE_COUNTER_2 */ | ||
427 | #define COUNTER2_SHIFT 0 | ||
428 | #define COUNTER2_MASK (0xffffffff << 0) | ||
429 | |||
430 | /* PERFORMANCE_COUNTER_CONFIG */ | ||
431 | #define CNTR2_MCONNID_EN_SHIFT 31 | ||
432 | #define CNTR2_MCONNID_EN_MASK (1 << 31) | ||
433 | #define CNTR2_REGION_EN_SHIFT 30 | ||
434 | #define CNTR2_REGION_EN_MASK (1 << 30) | ||
435 | #define CNTR2_CFG_SHIFT 16 | ||
436 | #define CNTR2_CFG_MASK (0xf << 16) | ||
437 | #define CNTR1_MCONNID_EN_SHIFT 15 | ||
438 | #define CNTR1_MCONNID_EN_MASK (1 << 15) | ||
439 | #define CNTR1_REGION_EN_SHIFT 14 | ||
440 | #define CNTR1_REGION_EN_MASK (1 << 14) | ||
441 | #define CNTR1_CFG_SHIFT 0 | ||
442 | #define CNTR1_CFG_MASK (0xf << 0) | ||
443 | |||
444 | /* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */ | ||
445 | #define MCONNID2_SHIFT 24 | ||
446 | #define MCONNID2_MASK (0xff << 24) | ||
447 | #define REGION_SEL2_SHIFT 16 | ||
448 | #define REGION_SEL2_MASK (0x3 << 16) | ||
449 | #define MCONNID1_SHIFT 8 | ||
450 | #define MCONNID1_MASK (0xff << 8) | ||
451 | #define REGION_SEL1_SHIFT 0 | ||
452 | #define REGION_SEL1_MASK (0x3 << 0) | ||
453 | |||
454 | /* PERFORMANCE_COUNTER_TIME */ | ||
455 | #define TOTAL_TIME_SHIFT 0 | ||
456 | #define TOTAL_TIME_MASK (0xffffffff << 0) | ||
457 | |||
458 | /* DLL_CALIB_CTRL */ | ||
459 | #define ACK_WAIT_SHIFT 16 | ||
460 | #define ACK_WAIT_MASK (0xf << 16) | ||
461 | #define DLL_CALIB_INTERVAL_SHIFT 0 | ||
462 | #define DLL_CALIB_INTERVAL_MASK (0x1ff << 0) | ||
463 | |||
464 | /* END_OF_INTERRUPT */ | ||
465 | #define EOI_SHIFT 0 | ||
466 | #define EOI_MASK (1 << 0) | ||
467 | |||
468 | /* SYSTEM_OCP_INTERRUPT_RAW_STATUS */ | ||
469 | #define DNV_SYS_SHIFT 2 | ||
470 | #define DNV_SYS_MASK (1 << 2) | ||
471 | #define TA_SYS_SHIFT 1 | ||
472 | #define TA_SYS_MASK (1 << 1) | ||
473 | #define ERR_SYS_SHIFT 0 | ||
474 | #define ERR_SYS_MASK (1 << 0) | ||
475 | |||
476 | /* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */ | ||
477 | #define DNV_LL_SHIFT 2 | ||
478 | #define DNV_LL_MASK (1 << 2) | ||
479 | #define TA_LL_SHIFT 1 | ||
480 | #define TA_LL_MASK (1 << 1) | ||
481 | #define ERR_LL_SHIFT 0 | ||
482 | #define ERR_LL_MASK (1 << 0) | ||
483 | |||
484 | /* SYSTEM_OCP_INTERRUPT_ENABLE_SET */ | ||
485 | #define EN_DNV_SYS_SHIFT 2 | ||
486 | #define EN_DNV_SYS_MASK (1 << 2) | ||
487 | #define EN_TA_SYS_SHIFT 1 | ||
488 | #define EN_TA_SYS_MASK (1 << 1) | ||
489 | #define EN_ERR_SYS_SHIFT 0 | ||
490 | #define EN_ERR_SYS_MASK (1 << 0) | ||
491 | |||
492 | /* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */ | ||
493 | #define EN_DNV_LL_SHIFT 2 | ||
494 | #define EN_DNV_LL_MASK (1 << 2) | ||
495 | #define EN_TA_LL_SHIFT 1 | ||
496 | #define EN_TA_LL_MASK (1 << 1) | ||
497 | #define EN_ERR_LL_SHIFT 0 | ||
498 | #define EN_ERR_LL_MASK (1 << 0) | ||
499 | |||
500 | /* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */ | ||
501 | #define ZQ_CS1EN_SHIFT 31 | ||
502 | #define ZQ_CS1EN_MASK (1 << 31) | ||
503 | #define ZQ_CS0EN_SHIFT 30 | ||
504 | #define ZQ_CS0EN_MASK (1 << 30) | ||
505 | #define ZQ_DUALCALEN_SHIFT 29 | ||
506 | #define ZQ_DUALCALEN_MASK (1 << 29) | ||
507 | #define ZQ_SFEXITEN_SHIFT 28 | ||
508 | #define ZQ_SFEXITEN_MASK (1 << 28) | ||
509 | #define ZQ_ZQINIT_MULT_SHIFT 18 | ||
510 | #define ZQ_ZQINIT_MULT_MASK (0x3 << 18) | ||
511 | #define ZQ_ZQCL_MULT_SHIFT 16 | ||
512 | #define ZQ_ZQCL_MULT_MASK (0x3 << 16) | ||
513 | #define ZQ_REFINTERVAL_SHIFT 0 | ||
514 | #define ZQ_REFINTERVAL_MASK (0xffff << 0) | ||
515 | |||
516 | /* TEMPERATURE_ALERT_CONFIG */ | ||
517 | #define TA_CS1EN_SHIFT 31 | ||
518 | #define TA_CS1EN_MASK (1 << 31) | ||
519 | #define TA_CS0EN_SHIFT 30 | ||
520 | #define TA_CS0EN_MASK (1 << 30) | ||
521 | #define TA_SFEXITEN_SHIFT 28 | ||
522 | #define TA_SFEXITEN_MASK (1 << 28) | ||
523 | #define TA_DEVWDT_SHIFT 26 | ||
524 | #define TA_DEVWDT_MASK (0x3 << 26) | ||
525 | #define TA_DEVCNT_SHIFT 24 | ||
526 | #define TA_DEVCNT_MASK (0x3 << 24) | ||
527 | #define TA_REFINTERVAL_SHIFT 0 | ||
528 | #define TA_REFINTERVAL_MASK (0x3fffff << 0) | ||
529 | |||
530 | /* OCP_ERROR_LOG */ | ||
531 | #define MADDRSPACE_SHIFT 14 | ||
532 | #define MADDRSPACE_MASK (0x3 << 14) | ||
533 | #define MBURSTSEQ_SHIFT 11 | ||
534 | #define MBURSTSEQ_MASK (0x7 << 11) | ||
535 | #define MCMD_SHIFT 8 | ||
536 | #define MCMD_MASK (0x7 << 8) | ||
537 | #define MCONNID_SHIFT 0 | ||
538 | #define MCONNID_MASK (0xff << 0) | ||
539 | |||
540 | /* DDR_PHY_CTRL_1 - EMIF4D */ | ||
541 | #define DLL_SLAVE_DLY_CTRL_SHIFT_4D 4 | ||
542 | #define DLL_SLAVE_DLY_CTRL_MASK_4D (0xFF << 4) | ||
543 | #define READ_LATENCY_SHIFT_4D 0 | ||
544 | #define READ_LATENCY_MASK_4D (0xf << 0) | ||
545 | |||
546 | /* DDR_PHY_CTRL_1 - EMIF4D5 */ | ||
547 | #define DLL_HALF_DELAY_SHIFT_4D5 21 | ||
548 | #define DLL_HALF_DELAY_MASK_4D5 (1 << 21) | ||
549 | #define READ_LATENCY_SHIFT_4D5 0 | ||
550 | #define READ_LATENCY_MASK_4D5 (0x1f << 0) | ||
551 | |||
552 | /* DDR_PHY_CTRL_1_SHDW */ | ||
553 | #define DDR_PHY_CTRL_1_SHDW_SHIFT 5 | ||
554 | #define DDR_PHY_CTRL_1_SHDW_MASK (0x7ffffff << 5) | ||
555 | #define READ_LATENCY_SHDW_SHIFT 0 | ||
556 | #define READ_LATENCY_SHDW_MASK (0x1f << 0) | ||
557 | |||
558 | #ifndef __ASSEMBLY__ | ||
559 | /* | ||
560 | * Structure containing shadow of important registers in EMIF | ||
561 | * The calculation function fills in this structure to be later used for | ||
562 | * initialisation and DVFS | ||
563 | */ | ||
564 | struct emif_regs { | ||
565 | u32 freq; | ||
566 | u32 ref_ctrl_shdw; | ||
567 | u32 ref_ctrl_shdw_derated; | ||
568 | u32 sdram_tim1_shdw; | ||
569 | u32 sdram_tim1_shdw_derated; | ||
570 | u32 sdram_tim2_shdw; | ||
571 | u32 sdram_tim3_shdw; | ||
572 | u32 sdram_tim3_shdw_derated; | ||
573 | u32 pwr_mgmt_ctrl_shdw; | ||
574 | union { | ||
575 | u32 read_idle_ctrl_shdw_normal; | ||
576 | u32 dll_calib_ctrl_shdw_normal; | ||
577 | }; | ||
578 | union { | ||
579 | u32 read_idle_ctrl_shdw_volt_ramp; | ||
580 | u32 dll_calib_ctrl_shdw_volt_ramp; | ||
581 | }; | ||
582 | |||
583 | u32 phy_ctrl_1_shdw; | ||
584 | u32 ext_phy_ctrl_2_shdw; | ||
585 | u32 ext_phy_ctrl_3_shdw; | ||
586 | u32 ext_phy_ctrl_4_shdw; | ||
587 | }; | ||
588 | #endif /* __ASSEMBLY__ */ | ||
589 | #endif /* __EMIF_H */ | ||
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c new file mode 100644 index 000000000000..3ed49c1c2b91 --- /dev/null +++ b/drivers/memory/tegra20-mc.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * Tegra20 Memory Controller | ||
3 | * | ||
4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/ratelimit.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/io.h> | ||
26 | |||
27 | #define DRV_NAME "tegra20-mc" | ||
28 | |||
29 | #define MC_INTSTATUS 0x0 | ||
30 | #define MC_INTMASK 0x4 | ||
31 | |||
32 | #define MC_INT_ERR_SHIFT 6 | ||
33 | #define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT) | ||
34 | #define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT) | ||
35 | #define MC_INT_INVALID_GART_PAGE BIT(MC_INT_ERR_SHIFT + 1) | ||
36 | #define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2) | ||
37 | #define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3) | ||
38 | |||
39 | #define MC_GART_ERROR_REQ 0x30 | ||
40 | #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 | ||
41 | #define MC_SECURITY_VIOLATION_STATUS 0x74 | ||
42 | |||
43 | #define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */ | ||
44 | |||
45 | #define MC_CLIENT_ID_MASK 0x3f | ||
46 | |||
47 | #define NUM_MC_REG_BANKS 2 | ||
48 | |||
49 | struct tegra20_mc { | ||
50 | void __iomem *regs[NUM_MC_REG_BANKS]; | ||
51 | struct device *dev; | ||
52 | }; | ||
53 | |||
54 | static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs) | ||
55 | { | ||
56 | u32 val = 0; | ||
57 | |||
58 | if (offs < 0x24) | ||
59 | val = readl(mc->regs[0] + offs); | ||
60 | if (offs < 0x400) | ||
61 | val = readl(mc->regs[1] + offs - 0x3c); | ||
62 | |||
63 | return val; | ||
64 | } | ||
65 | |||
66 | static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs) | ||
67 | { | ||
68 | if (offs < 0x24) { | ||
69 | writel(val, mc->regs[0] + offs); | ||
70 | return; | ||
71 | } | ||
72 | if (offs < 0x400) { | ||
73 | writel(val, mc->regs[1] + offs - 0x3c); | ||
74 | return; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | static const char * const tegra20_mc_client[] = { | ||
79 | "cbr_display0a", | ||
80 | "cbr_display0ab", | ||
81 | "cbr_display0b", | ||
82 | "cbr_display0bb", | ||
83 | "cbr_display0c", | ||
84 | "cbr_display0cb", | ||
85 | "cbr_display1b", | ||
86 | "cbr_display1bb", | ||
87 | "cbr_eppup", | ||
88 | "cbr_g2pr", | ||
89 | "cbr_g2sr", | ||
90 | "cbr_mpeunifbr", | ||
91 | "cbr_viruv", | ||
92 | "csr_avpcarm7r", | ||
93 | "csr_displayhc", | ||
94 | "csr_displayhcb", | ||
95 | "csr_fdcdrd", | ||
96 | "csr_g2dr", | ||
97 | "csr_host1xdmar", | ||
98 | "csr_host1xr", | ||
99 | "csr_idxsrd", | ||
100 | "csr_mpcorer", | ||
101 | "csr_mpe_ipred", | ||
102 | "csr_mpeamemrd", | ||
103 | "csr_mpecsrd", | ||
104 | "csr_ppcsahbdmar", | ||
105 | "csr_ppcsahbslvr", | ||
106 | "csr_texsrd", | ||
107 | "csr_vdebsevr", | ||
108 | "csr_vdember", | ||
109 | "csr_vdemcer", | ||
110 | "csr_vdetper", | ||
111 | "cbw_eppu", | ||
112 | "cbw_eppv", | ||
113 | "cbw_eppy", | ||
114 | "cbw_mpeunifbw", | ||
115 | "cbw_viwsb", | ||
116 | "cbw_viwu", | ||
117 | "cbw_viwv", | ||
118 | "cbw_viwy", | ||
119 | "ccw_g2dw", | ||
120 | "csw_avpcarm7w", | ||
121 | "csw_fdcdwr", | ||
122 | "csw_host1xw", | ||
123 | "csw_ispw", | ||
124 | "csw_mpcorew", | ||
125 | "csw_mpecswr", | ||
126 | "csw_ppcsahbdmaw", | ||
127 | "csw_ppcsahbslvw", | ||
128 | "csw_vdebsevw", | ||
129 | "csw_vdembew", | ||
130 | "csw_vdetpmw", | ||
131 | }; | ||
132 | |||
133 | static void tegra20_mc_decode(struct tegra20_mc *mc, int n) | ||
134 | { | ||
135 | u32 addr, req; | ||
136 | const char *client = "Unknown"; | ||
137 | int idx, cid; | ||
138 | const struct reg_info { | ||
139 | u32 offset; | ||
140 | u32 write_bit; /* 0=READ, 1=WRITE */ | ||
141 | int cid_shift; | ||
142 | char *message; | ||
143 | } reg[] = { | ||
144 | { | ||
145 | .offset = MC_DECERR_EMEM_OTHERS_STATUS, | ||
146 | .write_bit = 31, | ||
147 | .message = "MC_DECERR", | ||
148 | }, | ||
149 | { | ||
150 | .offset = MC_GART_ERROR_REQ, | ||
151 | .cid_shift = 1, | ||
152 | .message = "MC_GART_ERR", | ||
153 | |||
154 | }, | ||
155 | { | ||
156 | .offset = MC_SECURITY_VIOLATION_STATUS, | ||
157 | .write_bit = 31, | ||
158 | .message = "MC_SECURITY_ERR", | ||
159 | }, | ||
160 | }; | ||
161 | |||
162 | idx = n - MC_INT_ERR_SHIFT; | ||
163 | if ((idx < 0) || (idx >= ARRAY_SIZE(reg))) { | ||
164 | dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n", | ||
165 | BIT(n)); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | req = mc_readl(mc, reg[idx].offset); | ||
170 | cid = (req >> reg[idx].cid_shift) & MC_CLIENT_ID_MASK; | ||
171 | if (cid < ARRAY_SIZE(tegra20_mc_client)) | ||
172 | client = tegra20_mc_client[cid]; | ||
173 | |||
174 | addr = mc_readl(mc, reg[idx].offset + sizeof(u32)); | ||
175 | |||
176 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s)\n", | ||
177 | reg[idx].message, req, addr, client, | ||
178 | (req & BIT(reg[idx].write_bit)) ? "write" : "read", | ||
179 | (reg[idx].offset == MC_SECURITY_VIOLATION_STATUS) ? | ||
180 | ((req & SECURITY_VIOLATION_TYPE) ? | ||
181 | "carveout" : "trustzone") : ""); | ||
182 | } | ||
183 | |||
184 | static const struct of_device_id tegra20_mc_of_match[] __devinitconst = { | ||
185 | { .compatible = "nvidia,tegra20-mc", }, | ||
186 | {}, | ||
187 | }; | ||
188 | |||
189 | static irqreturn_t tegra20_mc_isr(int irq, void *data) | ||
190 | { | ||
191 | u32 stat, mask, bit; | ||
192 | struct tegra20_mc *mc = data; | ||
193 | |||
194 | stat = mc_readl(mc, MC_INTSTATUS); | ||
195 | mask = mc_readl(mc, MC_INTMASK); | ||
196 | mask &= stat; | ||
197 | if (!mask) | ||
198 | return IRQ_NONE; | ||
199 | while ((bit = ffs(mask)) != 0) | ||
200 | tegra20_mc_decode(mc, bit - 1); | ||
201 | mc_writel(mc, stat, MC_INTSTATUS); | ||
202 | return IRQ_HANDLED; | ||
203 | } | ||
204 | |||
205 | static int __devinit tegra20_mc_probe(struct platform_device *pdev) | ||
206 | { | ||
207 | struct resource *irq; | ||
208 | struct tegra20_mc *mc; | ||
209 | int i, err; | ||
210 | u32 intmask; | ||
211 | |||
212 | mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); | ||
213 | if (!mc) | ||
214 | return -ENOMEM; | ||
215 | mc->dev = &pdev->dev; | ||
216 | |||
217 | for (i = 0; i < ARRAY_SIZE(mc->regs); i++) { | ||
218 | struct resource *res; | ||
219 | |||
220 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
221 | if (!res) | ||
222 | return -ENODEV; | ||
223 | mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res); | ||
224 | if (!mc->regs[i]) | ||
225 | return -EBUSY; | ||
226 | } | ||
227 | |||
228 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
229 | if (!irq) | ||
230 | return -ENODEV; | ||
231 | err = devm_request_irq(&pdev->dev, irq->start, tegra20_mc_isr, | ||
232 | IRQF_SHARED, dev_name(&pdev->dev), mc); | ||
233 | if (err) | ||
234 | return -ENODEV; | ||
235 | |||
236 | platform_set_drvdata(pdev, mc); | ||
237 | |||
238 | intmask = MC_INT_INVALID_GART_PAGE | | ||
239 | MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION; | ||
240 | mc_writel(mc, intmask, MC_INTMASK); | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static struct platform_driver tegra20_mc_driver = { | ||
245 | .probe = tegra20_mc_probe, | ||
246 | .driver = { | ||
247 | .name = DRV_NAME, | ||
248 | .owner = THIS_MODULE, | ||
249 | .of_match_table = tegra20_mc_of_match, | ||
250 | }, | ||
251 | }; | ||
252 | module_platform_driver(tegra20_mc_driver); | ||
253 | |||
254 | MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); | ||
255 | MODULE_DESCRIPTION("Tegra20 MC driver"); | ||
256 | MODULE_LICENSE("GPL v2"); | ||
257 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c new file mode 100644 index 000000000000..e56ff04eb5cc --- /dev/null +++ b/drivers/memory/tegra30-mc.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * Tegra30 Memory Controller | ||
3 | * | ||
4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/ratelimit.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/io.h> | ||
26 | |||
27 | #define DRV_NAME "tegra30-mc" | ||
28 | |||
29 | #define MC_INTSTATUS 0x0 | ||
30 | #define MC_INTMASK 0x4 | ||
31 | |||
32 | #define MC_INT_ERR_SHIFT 6 | ||
33 | #define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT) | ||
34 | #define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT) | ||
35 | #define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2) | ||
36 | #define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3) | ||
37 | #define MC_INT_INVALID_SMMU_PAGE BIT(MC_INT_ERR_SHIFT + 4) | ||
38 | |||
39 | #define MC_ERR_STATUS 0x8 | ||
40 | #define MC_ERR_ADR 0xc | ||
41 | |||
42 | #define MC_ERR_TYPE_SHIFT 28 | ||
43 | #define MC_ERR_TYPE_MASK (7 << MC_ERR_TYPE_SHIFT) | ||
44 | #define MC_ERR_TYPE_DECERR_EMEM 2 | ||
45 | #define MC_ERR_TYPE_SECURITY_TRUSTZONE 3 | ||
46 | #define MC_ERR_TYPE_SECURITY_CARVEOUT 4 | ||
47 | #define MC_ERR_TYPE_INVALID_SMMU_PAGE 6 | ||
48 | |||
49 | #define MC_ERR_INVALID_SMMU_PAGE_SHIFT 25 | ||
50 | #define MC_ERR_INVALID_SMMU_PAGE_MASK (7 << MC_ERR_INVALID_SMMU_PAGE_SHIFT) | ||
51 | #define MC_ERR_RW_SHIFT 16 | ||
52 | #define MC_ERR_RW BIT(MC_ERR_RW_SHIFT) | ||
53 | #define MC_ERR_SECURITY BIT(MC_ERR_RW_SHIFT + 1) | ||
54 | |||
55 | #define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */ | ||
56 | |||
57 | #define MC_EMEM_ARB_CFG 0x90 | ||
58 | #define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 | ||
59 | #define MC_EMEM_ARB_TIMING_RCD 0x98 | ||
60 | #define MC_EMEM_ARB_TIMING_RP 0x9c | ||
61 | #define MC_EMEM_ARB_TIMING_RC 0xa0 | ||
62 | #define MC_EMEM_ARB_TIMING_RAS 0xa4 | ||
63 | #define MC_EMEM_ARB_TIMING_FAW 0xa8 | ||
64 | #define MC_EMEM_ARB_TIMING_RRD 0xac | ||
65 | #define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 | ||
66 | #define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 | ||
67 | #define MC_EMEM_ARB_TIMING_R2R 0xb8 | ||
68 | #define MC_EMEM_ARB_TIMING_W2W 0xbc | ||
69 | #define MC_EMEM_ARB_TIMING_R2W 0xc0 | ||
70 | #define MC_EMEM_ARB_TIMING_W2R 0xc4 | ||
71 | |||
72 | #define MC_EMEM_ARB_DA_TURNS 0xd0 | ||
73 | #define MC_EMEM_ARB_DA_COVERS 0xd4 | ||
74 | #define MC_EMEM_ARB_MISC0 0xd8 | ||
75 | #define MC_EMEM_ARB_MISC1 0xdc | ||
76 | |||
77 | #define MC_EMEM_ARB_RING3_THROTTLE 0xe4 | ||
78 | #define MC_EMEM_ARB_OVERRIDE 0xe8 | ||
79 | |||
80 | #define MC_TIMING_CONTROL 0xfc | ||
81 | |||
82 | #define MC_CLIENT_ID_MASK 0x7f | ||
83 | |||
84 | #define NUM_MC_REG_BANKS 4 | ||
85 | |||
86 | struct tegra30_mc { | ||
87 | void __iomem *regs[NUM_MC_REG_BANKS]; | ||
88 | struct device *dev; | ||
89 | u32 ctx[0]; | ||
90 | }; | ||
91 | |||
92 | static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs) | ||
93 | { | ||
94 | u32 val = 0; | ||
95 | |||
96 | if (offs < 0x10) | ||
97 | val = readl(mc->regs[0] + offs); | ||
98 | if (offs < 0x1f0) | ||
99 | val = readl(mc->regs[1] + offs - 0x3c); | ||
100 | if (offs < 0x228) | ||
101 | val = readl(mc->regs[2] + offs - 0x200); | ||
102 | if (offs < 0x400) | ||
103 | val = readl(mc->regs[3] + offs - 0x284); | ||
104 | |||
105 | return val; | ||
106 | } | ||
107 | |||
108 | static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs) | ||
109 | { | ||
110 | if (offs < 0x10) { | ||
111 | writel(val, mc->regs[0] + offs); | ||
112 | return; | ||
113 | } | ||
114 | if (offs < 0x1f0) { | ||
115 | writel(val, mc->regs[1] + offs - 0x3c); | ||
116 | return; | ||
117 | } | ||
118 | if (offs < 0x228) { | ||
119 | writel(val, mc->regs[2] + offs - 0x200); | ||
120 | return; | ||
121 | } | ||
122 | if (offs < 0x400) { | ||
123 | writel(val, mc->regs[3] + offs - 0x284); | ||
124 | return; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | static const char * const tegra30_mc_client[] = { | ||
129 | "csr_ptcr", | ||
130 | "cbr_display0a", | ||
131 | "cbr_display0ab", | ||
132 | "cbr_display0b", | ||
133 | "cbr_display0bb", | ||
134 | "cbr_display0c", | ||
135 | "cbr_display0cb", | ||
136 | "cbr_display1b", | ||
137 | "cbr_display1bb", | ||
138 | "cbr_eppup", | ||
139 | "cbr_g2pr", | ||
140 | "cbr_g2sr", | ||
141 | "cbr_mpeunifbr", | ||
142 | "cbr_viruv", | ||
143 | "csr_afir", | ||
144 | "csr_avpcarm7r", | ||
145 | "csr_displayhc", | ||
146 | "csr_displayhcb", | ||
147 | "csr_fdcdrd", | ||
148 | "csr_fdcdrd2", | ||
149 | "csr_g2dr", | ||
150 | "csr_hdar", | ||
151 | "csr_host1xdmar", | ||
152 | "csr_host1xr", | ||
153 | "csr_idxsrd", | ||
154 | "csr_idxsrd2", | ||
155 | "csr_mpe_ipred", | ||
156 | "csr_mpeamemrd", | ||
157 | "csr_mpecsrd", | ||
158 | "csr_ppcsahbdmar", | ||
159 | "csr_ppcsahbslvr", | ||
160 | "csr_satar", | ||
161 | "csr_texsrd", | ||
162 | "csr_texsrd2", | ||
163 | "csr_vdebsevr", | ||
164 | "csr_vdember", | ||
165 | "csr_vdemcer", | ||
166 | "csr_vdetper", | ||
167 | "csr_mpcorelpr", | ||
168 | "csr_mpcorer", | ||
169 | "cbw_eppu", | ||
170 | "cbw_eppv", | ||
171 | "cbw_eppy", | ||
172 | "cbw_mpeunifbw", | ||
173 | "cbw_viwsb", | ||
174 | "cbw_viwu", | ||
175 | "cbw_viwv", | ||
176 | "cbw_viwy", | ||
177 | "ccw_g2dw", | ||
178 | "csw_afiw", | ||
179 | "csw_avpcarm7w", | ||
180 | "csw_fdcdwr", | ||
181 | "csw_fdcdwr2", | ||
182 | "csw_hdaw", | ||
183 | "csw_host1xw", | ||
184 | "csw_ispw", | ||
185 | "csw_mpcorelpw", | ||
186 | "csw_mpcorew", | ||
187 | "csw_mpecswr", | ||
188 | "csw_ppcsahbdmaw", | ||
189 | "csw_ppcsahbslvw", | ||
190 | "csw_sataw", | ||
191 | "csw_vdebsevw", | ||
192 | "csw_vdedbgw", | ||
193 | "csw_vdembew", | ||
194 | "csw_vdetpmw", | ||
195 | }; | ||
196 | |||
197 | static void tegra30_mc_decode(struct tegra30_mc *mc, int n) | ||
198 | { | ||
199 | u32 err, addr; | ||
200 | const char * const mc_int_err[] = { | ||
201 | "MC_DECERR", | ||
202 | "Unknown", | ||
203 | "MC_SECURITY_ERR", | ||
204 | "MC_ARBITRATION_EMEM", | ||
205 | "MC_SMMU_ERR", | ||
206 | }; | ||
207 | const char * const err_type[] = { | ||
208 | "Unknown", | ||
209 | "Unknown", | ||
210 | "DECERR_EMEM", | ||
211 | "SECURITY_TRUSTZONE", | ||
212 | "SECURITY_CARVEOUT", | ||
213 | "Unknown", | ||
214 | "INVALID_SMMU_PAGE", | ||
215 | "Unknown", | ||
216 | }; | ||
217 | char attr[6]; | ||
218 | int cid, perm, type, idx; | ||
219 | const char *client = "Unknown"; | ||
220 | |||
221 | idx = n - MC_INT_ERR_SHIFT; | ||
222 | if ((idx < 0) || (idx >= ARRAY_SIZE(mc_int_err)) || (idx == 1)) { | ||
223 | dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n", | ||
224 | BIT(n)); | ||
225 | return; | ||
226 | } | ||
227 | |||
228 | err = readl(mc + MC_ERR_STATUS); | ||
229 | |||
230 | type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; | ||
231 | perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> | ||
232 | MC_ERR_INVALID_SMMU_PAGE_SHIFT; | ||
233 | if (type == MC_ERR_TYPE_INVALID_SMMU_PAGE) | ||
234 | sprintf(attr, "%c-%c-%c", | ||
235 | (perm & BIT(2)) ? 'R' : '-', | ||
236 | (perm & BIT(1)) ? 'W' : '-', | ||
237 | (perm & BIT(0)) ? 'S' : '-'); | ||
238 | else | ||
239 | attr[0] = '\0'; | ||
240 | |||
241 | cid = err & MC_CLIENT_ID_MASK; | ||
242 | if (cid < ARRAY_SIZE(tegra30_mc_client)) | ||
243 | client = tegra30_mc_client[cid]; | ||
244 | |||
245 | addr = readl(mc + MC_ERR_ADR); | ||
246 | |||
247 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", | ||
248 | mc_int_err[idx], err, addr, client, | ||
249 | (err & MC_ERR_SECURITY) ? "secure" : "non-secure", | ||
250 | (err & MC_ERR_RW) ? "write" : "read", | ||
251 | err_type[type], attr); | ||
252 | } | ||
253 | |||
254 | static const u32 tegra30_mc_ctx[] = { | ||
255 | MC_EMEM_ARB_CFG, | ||
256 | MC_EMEM_ARB_OUTSTANDING_REQ, | ||
257 | MC_EMEM_ARB_TIMING_RCD, | ||
258 | MC_EMEM_ARB_TIMING_RP, | ||
259 | MC_EMEM_ARB_TIMING_RC, | ||
260 | MC_EMEM_ARB_TIMING_RAS, | ||
261 | MC_EMEM_ARB_TIMING_FAW, | ||
262 | MC_EMEM_ARB_TIMING_RRD, | ||
263 | MC_EMEM_ARB_TIMING_RAP2PRE, | ||
264 | MC_EMEM_ARB_TIMING_WAP2PRE, | ||
265 | MC_EMEM_ARB_TIMING_R2R, | ||
266 | MC_EMEM_ARB_TIMING_W2W, | ||
267 | MC_EMEM_ARB_TIMING_R2W, | ||
268 | MC_EMEM_ARB_TIMING_W2R, | ||
269 | MC_EMEM_ARB_DA_TURNS, | ||
270 | MC_EMEM_ARB_DA_COVERS, | ||
271 | MC_EMEM_ARB_MISC0, | ||
272 | MC_EMEM_ARB_MISC1, | ||
273 | MC_EMEM_ARB_RING3_THROTTLE, | ||
274 | MC_EMEM_ARB_OVERRIDE, | ||
275 | MC_INTMASK, | ||
276 | }; | ||
277 | |||
278 | static int tegra30_mc_suspend(struct device *dev) | ||
279 | { | ||
280 | int i; | ||
281 | struct tegra30_mc *mc = dev_get_drvdata(dev); | ||
282 | |||
283 | for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++) | ||
284 | mc->ctx[i] = mc_readl(mc, tegra30_mc_ctx[i]); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int tegra30_mc_resume(struct device *dev) | ||
289 | { | ||
290 | int i; | ||
291 | struct tegra30_mc *mc = dev_get_drvdata(dev); | ||
292 | |||
293 | for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++) | ||
294 | mc_writel(mc, mc->ctx[i], tegra30_mc_ctx[i]); | ||
295 | |||
296 | mc_writel(mc, 1, MC_TIMING_CONTROL); | ||
297 | /* Read-back to ensure that write reached */ | ||
298 | mc_readl(mc, MC_TIMING_CONTROL); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm, | ||
303 | tegra30_mc_suspend, | ||
304 | tegra30_mc_resume, NULL); | ||
305 | |||
306 | static const struct of_device_id tegra30_mc_of_match[] __devinitconst = { | ||
307 | { .compatible = "nvidia,tegra30-mc", }, | ||
308 | {}, | ||
309 | }; | ||
310 | |||
311 | static irqreturn_t tegra30_mc_isr(int irq, void *data) | ||
312 | { | ||
313 | u32 stat, mask, bit; | ||
314 | struct tegra30_mc *mc = data; | ||
315 | |||
316 | stat = mc_readl(mc, MC_INTSTATUS); | ||
317 | mask = mc_readl(mc, MC_INTMASK); | ||
318 | mask &= stat; | ||
319 | if (!mask) | ||
320 | return IRQ_NONE; | ||
321 | while ((bit = ffs(mask)) != 0) | ||
322 | tegra30_mc_decode(mc, bit - 1); | ||
323 | mc_writel(mc, stat, MC_INTSTATUS); | ||
324 | return IRQ_HANDLED; | ||
325 | } | ||
326 | |||
327 | static int __devinit tegra30_mc_probe(struct platform_device *pdev) | ||
328 | { | ||
329 | struct resource *irq; | ||
330 | struct tegra30_mc *mc; | ||
331 | size_t bytes; | ||
332 | int err, i; | ||
333 | u32 intmask; | ||
334 | |||
335 | bytes = sizeof(*mc) + sizeof(u32) * ARRAY_SIZE(tegra30_mc_ctx); | ||
336 | mc = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL); | ||
337 | if (!mc) | ||
338 | return -ENOMEM; | ||
339 | mc->dev = &pdev->dev; | ||
340 | |||
341 | for (i = 0; i < ARRAY_SIZE(mc->regs); i++) { | ||
342 | struct resource *res; | ||
343 | |||
344 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
345 | if (!res) | ||
346 | return -ENODEV; | ||
347 | mc->regs[i] = devm_request_and_ioremap(&pdev->dev, res); | ||
348 | if (!mc->regs[i]) | ||
349 | return -EBUSY; | ||
350 | } | ||
351 | |||
352 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
353 | if (!irq) | ||
354 | return -ENODEV; | ||
355 | err = devm_request_irq(&pdev->dev, irq->start, tegra30_mc_isr, | ||
356 | IRQF_SHARED, dev_name(&pdev->dev), mc); | ||
357 | if (err) | ||
358 | return -ENODEV; | ||
359 | |||
360 | platform_set_drvdata(pdev, mc); | ||
361 | |||
362 | intmask = MC_INT_INVALID_SMMU_PAGE | | ||
363 | MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION; | ||
364 | mc_writel(mc, intmask, MC_INTMASK); | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static struct platform_driver tegra30_mc_driver = { | ||
369 | .probe = tegra30_mc_probe, | ||
370 | .driver = { | ||
371 | .name = DRV_NAME, | ||
372 | .owner = THIS_MODULE, | ||
373 | .of_match_table = tegra30_mc_of_match, | ||
374 | .pm = &tegra30_mc_pm, | ||
375 | }, | ||
376 | }; | ||
377 | module_platform_driver(tegra30_mc_driver); | ||
378 | |||
379 | MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); | ||
380 | MODULE_DESCRIPTION("Tegra30 MC driver"); | ||
381 | MODULE_LICENSE("GPL v2"); | ||
382 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 968469555956..757fbd0f2a14 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -508,14 +508,6 @@ config USB_SWITCH_FSA9480 | |||
508 | stereo and mono audio, video, microphone and UART data to use | 508 | stereo and mono audio, video, microphone and UART data to use |
509 | a common connector port. | 509 | a common connector port. |
510 | 510 | ||
511 | config MAX8997_MUIC | ||
512 | tristate "MAX8997 MUIC Support" | ||
513 | depends on MFD_MAX8997 | ||
514 | help | ||
515 | If you say yes here you get support for the MUIC device of | ||
516 | Maxim MAX8997 PMIC. | ||
517 | The MAX8997 MUIC is a USB port accessory detector and switch. | ||
518 | |||
519 | source "drivers/misc/c2port/Kconfig" | 511 | source "drivers/misc/c2port/Kconfig" |
520 | source "drivers/misc/eeprom/Kconfig" | 512 | source "drivers/misc/eeprom/Kconfig" |
521 | source "drivers/misc/cb710/Kconfig" | 513 | source "drivers/misc/cb710/Kconfig" |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 509d0569dc04..162861788c6d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -50,4 +50,3 @@ obj-y += lis3lv02d/ | |||
50 | obj-y += carma/ | 50 | obj-y += carma/ |
51 | obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o | 51 | obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o |
52 | obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ | 52 | obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ |
53 | obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o | ||
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 402956321d33..5abffe58a9d2 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2075,7 +2075,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
2075 | 2075 | ||
2076 | printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); | 2076 | printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); |
2077 | if (p->base_hi && priv->ecr) | 2077 | if (p->base_hi && priv->ecr) |
2078 | printk(" (0x%lx)", p->base_hi); | 2078 | printk(KERN_CONT " (0x%lx)", p->base_hi); |
2079 | if (p->irq == PARPORT_IRQ_AUTO) { | 2079 | if (p->irq == PARPORT_IRQ_AUTO) { |
2080 | p->irq = PARPORT_IRQ_NONE; | 2080 | p->irq = PARPORT_IRQ_NONE; |
2081 | parport_irq_probe(p); | 2081 | parport_irq_probe(p); |
@@ -2086,7 +2086,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
2086 | p->irq = PARPORT_IRQ_NONE; | 2086 | p->irq = PARPORT_IRQ_NONE; |
2087 | } | 2087 | } |
2088 | if (p->irq != PARPORT_IRQ_NONE) { | 2088 | if (p->irq != PARPORT_IRQ_NONE) { |
2089 | printk(", irq %d", p->irq); | 2089 | printk(KERN_CONT ", irq %d", p->irq); |
2090 | priv->ctr_writable |= 0x10; | 2090 | priv->ctr_writable |= 0x10; |
2091 | 2091 | ||
2092 | if (p->dma == PARPORT_DMA_AUTO) { | 2092 | if (p->dma == PARPORT_DMA_AUTO) { |
@@ -2110,21 +2110,21 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
2110 | /* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */ | 2110 | /* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */ |
2111 | #endif /* IEEE 1284 support */ | 2111 | #endif /* IEEE 1284 support */ |
2112 | if (p->dma != PARPORT_DMA_NONE) { | 2112 | if (p->dma != PARPORT_DMA_NONE) { |
2113 | printk(", dma %d", p->dma); | 2113 | printk(KERN_CONT ", dma %d", p->dma); |
2114 | p->modes |= PARPORT_MODE_DMA; | 2114 | p->modes |= PARPORT_MODE_DMA; |
2115 | } else | 2115 | } else |
2116 | printk(", using FIFO"); | 2116 | printk(KERN_CONT ", using FIFO"); |
2117 | } else | 2117 | } else |
2118 | /* We can't use the DMA channel after all. */ | 2118 | /* We can't use the DMA channel after all. */ |
2119 | p->dma = PARPORT_DMA_NONE; | 2119 | p->dma = PARPORT_DMA_NONE; |
2120 | #endif /* Allowed to use FIFO/DMA */ | 2120 | #endif /* Allowed to use FIFO/DMA */ |
2121 | 2121 | ||
2122 | printk(" ["); | 2122 | printk(KERN_CONT " ["); |
2123 | 2123 | ||
2124 | #define printmode(x) \ | 2124 | #define printmode(x) \ |
2125 | {\ | 2125 | {\ |
2126 | if (p->modes & PARPORT_MODE_##x) {\ | 2126 | if (p->modes & PARPORT_MODE_##x) {\ |
2127 | printk("%s%s", f ? "," : "", #x);\ | 2127 | printk(KERN_CONT "%s%s", f ? "," : "", #x);\ |
2128 | f++;\ | 2128 | f++;\ |
2129 | } \ | 2129 | } \ |
2130 | } | 2130 | } |
@@ -2140,9 +2140,9 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
2140 | } | 2140 | } |
2141 | #undef printmode | 2141 | #undef printmode |
2142 | #ifndef CONFIG_PARPORT_1284 | 2142 | #ifndef CONFIG_PARPORT_1284 |
2143 | printk("(,...)"); | 2143 | printk(KERN_CONT "(,...)"); |
2144 | #endif /* CONFIG_PARPORT_1284 */ | 2144 | #endif /* CONFIG_PARPORT_1284 */ |
2145 | printk("]\n"); | 2145 | printk(KERN_CONT "]\n"); |
2146 | if (probedirq != PARPORT_IRQ_NONE) | 2146 | if (probedirq != PARPORT_IRQ_NONE) |
2147 | printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); | 2147 | printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); |
2148 | 2148 | ||
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index eb1dee26bda3..c706635f3f82 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig | |||
@@ -53,8 +53,6 @@ config ANDROID_LOW_MEMORY_KILLER | |||
53 | ---help--- | 53 | ---help--- |
54 | Register processes to be killed when memory is low | 54 | Register processes to be killed when memory is low |
55 | 55 | ||
56 | source "drivers/staging/android/switch/Kconfig" | ||
57 | |||
58 | config ANDROID_INTF_ALARM | 56 | config ANDROID_INTF_ALARM |
59 | bool "Android alarm driver" | 57 | bool "Android alarm driver" |
60 | depends on RTC_CLASS | 58 | depends on RTC_CLASS |
@@ -80,7 +78,6 @@ config ANDROID_ALARM_OLDDRV_COMPAT | |||
80 | Provides preprocessor alias to aid compatability with | 78 | Provides preprocessor alias to aid compatability with |
81 | older out-of-tree drivers that use the Android Alarm | 79 | older out-of-tree drivers that use the Android Alarm |
82 | in-kernel API. This will be removed eventually. | 80 | in-kernel API. This will be removed eventually. |
83 | |||
84 | endif # if ANDROID | 81 | endif # if ANDROID |
85 | 82 | ||
86 | endmenu | 83 | endmenu |
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 9b6c9ed91f69..045d17bde524 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile | |||
@@ -6,6 +6,5 @@ obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o | |||
6 | obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o | 6 | obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o |
7 | obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o | 7 | obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o |
8 | obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o | 8 | obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o |
9 | obj-$(CONFIG_ANDROID_SWITCH) += switch/ | ||
10 | obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o | 9 | obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o |
11 | obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o | 10 | obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o |
diff --git a/drivers/staging/android/switch/Kconfig b/drivers/staging/android/switch/Kconfig deleted file mode 100644 index 36846f62f4bc..000000000000 --- a/drivers/staging/android/switch/Kconfig +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | menuconfig ANDROID_SWITCH | ||
2 | tristate "Android Switch class support" | ||
3 | help | ||
4 | Say Y here to enable Android switch class support. This allows | ||
5 | monitoring switches by userspace via sysfs and uevent. | ||
6 | |||
7 | config ANDROID_SWITCH_GPIO | ||
8 | tristate "Android GPIO Switch support" | ||
9 | depends on GENERIC_GPIO && ANDROID_SWITCH | ||
10 | help | ||
11 | Say Y here to enable GPIO based switch support. | ||
diff --git a/drivers/staging/android/switch/Makefile b/drivers/staging/android/switch/Makefile deleted file mode 100644 index d76bfdcedfaf..000000000000 --- a/drivers/staging/android/switch/Makefile +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | # Android Switch Class Driver | ||
2 | obj-$(CONFIG_ANDROID_SWITCH) += switch_class.o | ||
3 | obj-$(CONFIG_ANDROID_SWITCH_GPIO) += switch_gpio.o | ||
4 | |||
diff --git a/drivers/staging/android/switch/switch.h b/drivers/staging/android/switch/switch.h deleted file mode 100644 index 4fcb3109875a..000000000000 --- a/drivers/staging/android/switch/switch.h +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /* | ||
2 | * Switch class driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Google, Inc. | ||
5 | * Author: Mike Lockwood <lockwood@android.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __LINUX_SWITCH_H__ | ||
19 | #define __LINUX_SWITCH_H__ | ||
20 | |||
21 | struct switch_dev { | ||
22 | const char *name; | ||
23 | struct device *dev; | ||
24 | int index; | ||
25 | int state; | ||
26 | |||
27 | ssize_t (*print_name)(struct switch_dev *sdev, char *buf); | ||
28 | ssize_t (*print_state)(struct switch_dev *sdev, char *buf); | ||
29 | }; | ||
30 | |||
31 | struct gpio_switch_platform_data { | ||
32 | const char *name; | ||
33 | unsigned gpio; | ||
34 | |||
35 | /* if NULL, switch_dev.name will be printed */ | ||
36 | const char *name_on; | ||
37 | const char *name_off; | ||
38 | /* if NULL, "0" or "1" will be printed */ | ||
39 | const char *state_on; | ||
40 | const char *state_off; | ||
41 | }; | ||
42 | |||
43 | extern int switch_dev_register(struct switch_dev *sdev); | ||
44 | extern void switch_dev_unregister(struct switch_dev *sdev); | ||
45 | |||
46 | static inline int switch_get_state(struct switch_dev *sdev) | ||
47 | { | ||
48 | return sdev->state; | ||
49 | } | ||
50 | |||
51 | extern void switch_set_state(struct switch_dev *sdev, int state); | ||
52 | |||
53 | #endif /* __LINUX_SWITCH_H__ */ | ||
diff --git a/drivers/staging/android/switch/switch_class.c b/drivers/staging/android/switch/switch_class.c deleted file mode 100644 index 74680446fc66..000000000000 --- a/drivers/staging/android/switch/switch_class.c +++ /dev/null | |||
@@ -1,174 +0,0 @@ | |||
1 | /* | ||
2 | * switch_class.c | ||
3 | * | ||
4 | * Copyright (C) 2008 Google, Inc. | ||
5 | * Author: Mike Lockwood <lockwood@android.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/err.h> | ||
24 | #include "switch.h" | ||
25 | |||
26 | struct class *switch_class; | ||
27 | static atomic_t device_count; | ||
28 | |||
29 | static ssize_t state_show(struct device *dev, struct device_attribute *attr, | ||
30 | char *buf) | ||
31 | { | ||
32 | struct switch_dev *sdev = (struct switch_dev *) | ||
33 | dev_get_drvdata(dev); | ||
34 | |||
35 | if (sdev->print_state) { | ||
36 | int ret = sdev->print_state(sdev, buf); | ||
37 | if (ret >= 0) | ||
38 | return ret; | ||
39 | } | ||
40 | return sprintf(buf, "%d\n", sdev->state); | ||
41 | } | ||
42 | |||
43 | static ssize_t name_show(struct device *dev, struct device_attribute *attr, | ||
44 | char *buf) | ||
45 | { | ||
46 | struct switch_dev *sdev = (struct switch_dev *) | ||
47 | dev_get_drvdata(dev); | ||
48 | |||
49 | if (sdev->print_name) { | ||
50 | int ret = sdev->print_name(sdev, buf); | ||
51 | if (ret >= 0) | ||
52 | return ret; | ||
53 | } | ||
54 | return sprintf(buf, "%s\n", sdev->name); | ||
55 | } | ||
56 | |||
57 | static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, state_show, NULL); | ||
58 | static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, name_show, NULL); | ||
59 | |||
60 | void switch_set_state(struct switch_dev *sdev, int state) | ||
61 | { | ||
62 | char name_buf[120]; | ||
63 | char state_buf[120]; | ||
64 | char *prop_buf; | ||
65 | char *envp[3]; | ||
66 | int env_offset = 0; | ||
67 | int length; | ||
68 | |||
69 | if (sdev->state != state) { | ||
70 | sdev->state = state; | ||
71 | |||
72 | prop_buf = (char *)get_zeroed_page(GFP_KERNEL); | ||
73 | if (prop_buf) { | ||
74 | length = name_show(sdev->dev, NULL, prop_buf); | ||
75 | if (length > 0) { | ||
76 | if (prop_buf[length - 1] == '\n') | ||
77 | prop_buf[length - 1] = 0; | ||
78 | snprintf(name_buf, sizeof(name_buf), | ||
79 | "SWITCH_NAME=%s", prop_buf); | ||
80 | envp[env_offset++] = name_buf; | ||
81 | } | ||
82 | length = state_show(sdev->dev, NULL, prop_buf); | ||
83 | if (length > 0) { | ||
84 | if (prop_buf[length - 1] == '\n') | ||
85 | prop_buf[length - 1] = 0; | ||
86 | snprintf(state_buf, sizeof(state_buf), | ||
87 | "SWITCH_STATE=%s", prop_buf); | ||
88 | envp[env_offset++] = state_buf; | ||
89 | } | ||
90 | envp[env_offset] = NULL; | ||
91 | kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp); | ||
92 | free_page((unsigned long)prop_buf); | ||
93 | } else { | ||
94 | printk(KERN_ERR "out of memory in switch_set_state\n"); | ||
95 | kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE); | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(switch_set_state); | ||
100 | |||
101 | static int create_switch_class(void) | ||
102 | { | ||
103 | if (!switch_class) { | ||
104 | switch_class = class_create(THIS_MODULE, "switch"); | ||
105 | if (IS_ERR(switch_class)) | ||
106 | return PTR_ERR(switch_class); | ||
107 | atomic_set(&device_count, 0); | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | int switch_dev_register(struct switch_dev *sdev) | ||
114 | { | ||
115 | int ret; | ||
116 | |||
117 | if (!switch_class) { | ||
118 | ret = create_switch_class(); | ||
119 | if (ret < 0) | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | sdev->index = atomic_inc_return(&device_count); | ||
124 | sdev->dev = device_create(switch_class, NULL, | ||
125 | MKDEV(0, sdev->index), NULL, sdev->name); | ||
126 | if (IS_ERR(sdev->dev)) | ||
127 | return PTR_ERR(sdev->dev); | ||
128 | |||
129 | ret = device_create_file(sdev->dev, &dev_attr_state); | ||
130 | if (ret < 0) | ||
131 | goto err_create_file_1; | ||
132 | ret = device_create_file(sdev->dev, &dev_attr_name); | ||
133 | if (ret < 0) | ||
134 | goto err_create_file_2; | ||
135 | |||
136 | dev_set_drvdata(sdev->dev, sdev); | ||
137 | sdev->state = 0; | ||
138 | return 0; | ||
139 | |||
140 | err_create_file_2: | ||
141 | device_remove_file(sdev->dev, &dev_attr_state); | ||
142 | err_create_file_1: | ||
143 | device_destroy(switch_class, MKDEV(0, sdev->index)); | ||
144 | printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name); | ||
145 | |||
146 | return ret; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(switch_dev_register); | ||
149 | |||
150 | void switch_dev_unregister(struct switch_dev *sdev) | ||
151 | { | ||
152 | device_remove_file(sdev->dev, &dev_attr_name); | ||
153 | device_remove_file(sdev->dev, &dev_attr_state); | ||
154 | device_destroy(switch_class, MKDEV(0, sdev->index)); | ||
155 | dev_set_drvdata(sdev->dev, NULL); | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(switch_dev_unregister); | ||
158 | |||
159 | static int __init switch_class_init(void) | ||
160 | { | ||
161 | return create_switch_class(); | ||
162 | } | ||
163 | |||
164 | static void __exit switch_class_exit(void) | ||
165 | { | ||
166 | class_destroy(switch_class); | ||
167 | } | ||
168 | |||
169 | module_init(switch_class_init); | ||
170 | module_exit(switch_class_exit); | ||
171 | |||
172 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
173 | MODULE_DESCRIPTION("Switch class driver"); | ||
174 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/android/switch/switch_gpio.c b/drivers/staging/android/switch/switch_gpio.c deleted file mode 100644 index 38b2c2f6004e..000000000000 --- a/drivers/staging/android/switch/switch_gpio.c +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /* | ||
2 | * switch_gpio.c | ||
3 | * | ||
4 | * Copyright (C) 2008 Google, Inc. | ||
5 | * Author: Mike Lockwood <lockwood@android.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | #include <linux/gpio.h> | ||
26 | #include "switch.h" | ||
27 | |||
28 | struct gpio_switch_data { | ||
29 | struct switch_dev sdev; | ||
30 | unsigned gpio; | ||
31 | const char *name_on; | ||
32 | const char *name_off; | ||
33 | const char *state_on; | ||
34 | const char *state_off; | ||
35 | int irq; | ||
36 | struct work_struct work; | ||
37 | }; | ||
38 | |||
39 | static void gpio_switch_work(struct work_struct *work) | ||
40 | { | ||
41 | int state; | ||
42 | struct gpio_switch_data *data = | ||
43 | container_of(work, struct gpio_switch_data, work); | ||
44 | |||
45 | state = gpio_get_value(data->gpio); | ||
46 | switch_set_state(&data->sdev, state); | ||
47 | } | ||
48 | |||
49 | static irqreturn_t gpio_irq_handler(int irq, void *dev_id) | ||
50 | { | ||
51 | struct gpio_switch_data *switch_data = | ||
52 | (struct gpio_switch_data *)dev_id; | ||
53 | |||
54 | schedule_work(&switch_data->work); | ||
55 | return IRQ_HANDLED; | ||
56 | } | ||
57 | |||
58 | static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf) | ||
59 | { | ||
60 | struct gpio_switch_data *switch_data = | ||
61 | container_of(sdev, struct gpio_switch_data, sdev); | ||
62 | const char *state; | ||
63 | if (switch_get_state(sdev)) | ||
64 | state = switch_data->state_on; | ||
65 | else | ||
66 | state = switch_data->state_off; | ||
67 | |||
68 | if (state) | ||
69 | return sprintf(buf, "%s\n", state); | ||
70 | return -1; | ||
71 | } | ||
72 | |||
73 | static int gpio_switch_probe(struct platform_device *pdev) | ||
74 | { | ||
75 | struct gpio_switch_platform_data *pdata = pdev->dev.platform_data; | ||
76 | struct gpio_switch_data *switch_data; | ||
77 | int ret = 0; | ||
78 | |||
79 | if (!pdata) | ||
80 | return -EBUSY; | ||
81 | |||
82 | switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL); | ||
83 | if (!switch_data) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | switch_data->sdev.name = pdata->name; | ||
87 | switch_data->gpio = pdata->gpio; | ||
88 | switch_data->name_on = pdata->name_on; | ||
89 | switch_data->name_off = pdata->name_off; | ||
90 | switch_data->state_on = pdata->state_on; | ||
91 | switch_data->state_off = pdata->state_off; | ||
92 | switch_data->sdev.print_state = switch_gpio_print_state; | ||
93 | |||
94 | ret = switch_dev_register(&switch_data->sdev); | ||
95 | if (ret < 0) | ||
96 | goto err_switch_dev_register; | ||
97 | |||
98 | ret = gpio_request(switch_data->gpio, pdev->name); | ||
99 | if (ret < 0) | ||
100 | goto err_request_gpio; | ||
101 | |||
102 | ret = gpio_direction_input(switch_data->gpio); | ||
103 | if (ret < 0) | ||
104 | goto err_set_gpio_input; | ||
105 | |||
106 | INIT_WORK(&switch_data->work, gpio_switch_work); | ||
107 | |||
108 | switch_data->irq = gpio_to_irq(switch_data->gpio); | ||
109 | if (switch_data->irq < 0) { | ||
110 | ret = switch_data->irq; | ||
111 | goto err_detect_irq_num_failed; | ||
112 | } | ||
113 | |||
114 | ret = request_irq(switch_data->irq, gpio_irq_handler, | ||
115 | IRQF_TRIGGER_LOW, pdev->name, switch_data); | ||
116 | if (ret < 0) | ||
117 | goto err_request_irq; | ||
118 | |||
119 | /* Perform initial detection */ | ||
120 | gpio_switch_work(&switch_data->work); | ||
121 | |||
122 | return 0; | ||
123 | |||
124 | err_request_irq: | ||
125 | err_detect_irq_num_failed: | ||
126 | err_set_gpio_input: | ||
127 | gpio_free(switch_data->gpio); | ||
128 | err_request_gpio: | ||
129 | switch_dev_unregister(&switch_data->sdev); | ||
130 | err_switch_dev_register: | ||
131 | kfree(switch_data); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | static int __devexit gpio_switch_remove(struct platform_device *pdev) | ||
137 | { | ||
138 | struct gpio_switch_data *switch_data = platform_get_drvdata(pdev); | ||
139 | |||
140 | cancel_work_sync(&switch_data->work); | ||
141 | gpio_free(switch_data->gpio); | ||
142 | switch_dev_unregister(&switch_data->sdev); | ||
143 | kfree(switch_data); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static struct platform_driver gpio_switch_driver = { | ||
149 | .probe = gpio_switch_probe, | ||
150 | .remove = __devexit_p(gpio_switch_remove), | ||
151 | .driver = { | ||
152 | .name = "switch-gpio", | ||
153 | .owner = THIS_MODULE, | ||
154 | }, | ||
155 | }; | ||
156 | |||
157 | static int __init gpio_switch_init(void) | ||
158 | { | ||
159 | return platform_driver_register(&gpio_switch_driver); | ||
160 | } | ||
161 | |||
162 | static void __exit gpio_switch_exit(void) | ||
163 | { | ||
164 | platform_driver_unregister(&gpio_switch_driver); | ||
165 | } | ||
166 | |||
167 | module_init(gpio_switch_init); | ||
168 | module_exit(gpio_switch_exit); | ||
169 | |||
170 | MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); | ||
171 | MODULE_DESCRIPTION("GPIO Switch driver"); | ||
172 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index b98371d93a92..42202cd83158 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c | |||
@@ -146,6 +146,14 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev) | |||
146 | priv->flags = 0; /* interrupt is enabled to begin with */ | 146 | priv->flags = 0; /* interrupt is enabled to begin with */ |
147 | priv->pdev = pdev; | 147 | priv->pdev = pdev; |
148 | 148 | ||
149 | if (!uioinfo->irq) { | ||
150 | ret = platform_get_irq(pdev, 0); | ||
151 | if (ret < 0) { | ||
152 | dev_err(&pdev->dev, "failed to get IRQ\n"); | ||
153 | goto bad0; | ||
154 | } | ||
155 | uioinfo->irq = ret; | ||
156 | } | ||
149 | uiomem = &uioinfo->mem[0]; | 157 | uiomem = &uioinfo->mem[0]; |
150 | 158 | ||
151 | for (i = 0; i < pdev->num_resources; ++i) { | 159 | for (i = 0; i < pdev->num_resources; ++i) { |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 566d9f94f735..9a56e3adf476 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -73,7 +73,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr, | |||
73 | return (value < 0) ? value : count; | 73 | return (value < 0) ? value : count; |
74 | } | 74 | } |
75 | 75 | ||
76 | static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, | 76 | static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR, |
77 | show_bConfigurationValue, set_bConfigurationValue); | 77 | show_bConfigurationValue, set_bConfigurationValue); |
78 | 78 | ||
79 | /* String fields */ | 79 | /* String fields */ |
@@ -595,7 +595,7 @@ static ssize_t usb_dev_authorized_store(struct device *dev, | |||
595 | return result < 0? result : size; | 595 | return result < 0? result : size; |
596 | } | 596 | } |
597 | 597 | ||
598 | static DEVICE_ATTR(authorized, 0644, | 598 | static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, 0644, |
599 | usb_dev_authorized_show, usb_dev_authorized_store); | 599 | usb_dev_authorized_show, usb_dev_authorized_store); |
600 | 600 | ||
601 | /* "Safely remove a device" */ | 601 | /* "Safely remove a device" */ |
@@ -618,7 +618,7 @@ static ssize_t usb_remove_store(struct device *dev, | |||
618 | usb_unlock_device(udev); | 618 | usb_unlock_device(udev); |
619 | return rc; | 619 | return rc; |
620 | } | 620 | } |
621 | static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store); | 621 | static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, usb_remove_store); |
622 | 622 | ||
623 | 623 | ||
624 | static struct attribute *dev_attrs[] = { | 624 | static struct attribute *dev_attrs[] = { |
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c index 7c8cdb8aed26..8e813eed0f0a 100644 --- a/drivers/w1/slaves/w1_ds2408.c +++ b/drivers/w1/slaves/w1_ds2408.c | |||
@@ -332,7 +332,6 @@ static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { | |||
332 | }, | 332 | }, |
333 | .size = 1, | 333 | .size = 1, |
334 | .read = w1_f29_read_cond_search_mask, | 334 | .read = w1_f29_read_cond_search_mask, |
335 | .write = 0, | ||
336 | }, | 335 | }, |
337 | { | 336 | { |
338 | .attr = { | 337 | .attr = { |
@@ -341,7 +340,6 @@ static struct bin_attribute w1_f29_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { | |||
341 | }, | 340 | }, |
342 | .size = 1, | 341 | .size = 1, |
343 | .read = w1_f29_read_cond_search_polarity, | 342 | .read = w1_f29_read_cond_search_polarity, |
344 | .write = 0, | ||
345 | }, | 343 | }, |
346 | { | 344 | { |
347 | .attr = { | 345 | .attr = { |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 9761950697b4..2f2e894ea0c8 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -1027,7 +1027,7 @@ static int __init w1_init(void) | |||
1027 | retval = driver_register(&w1_slave_driver); | 1027 | retval = driver_register(&w1_slave_driver); |
1028 | if (retval) { | 1028 | if (retval) { |
1029 | printk(KERN_ERR | 1029 | printk(KERN_ERR |
1030 | "Failed to register master driver. err=%d.\n", | 1030 | "Failed to register slave driver. err=%d.\n", |
1031 | retval); | 1031 | retval); |
1032 | goto err_out_master_unregister; | 1032 | goto err_out_master_unregister; |
1033 | } | 1033 | } |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 3135b2c63998..e10acc237733 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
@@ -31,6 +31,9 @@ | |||
31 | static int w1_delay_parm = 1; | 31 | static int w1_delay_parm = 1; |
32 | module_param_named(delay_coef, w1_delay_parm, int, 0); | 32 | module_param_named(delay_coef, w1_delay_parm, int, 0); |
33 | 33 | ||
34 | static int w1_disable_irqs = 0; | ||
35 | module_param_named(disable_irqs, w1_disable_irqs, int, 0); | ||
36 | |||
34 | static u8 w1_crc8_table[] = { | 37 | static u8 w1_crc8_table[] = { |
35 | 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, | 38 | 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, |
36 | 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, | 39 | 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, |
@@ -79,6 +82,10 @@ static u8 w1_touch_bit(struct w1_master *dev, int bit) | |||
79 | */ | 82 | */ |
80 | static void w1_write_bit(struct w1_master *dev, int bit) | 83 | static void w1_write_bit(struct w1_master *dev, int bit) |
81 | { | 84 | { |
85 | unsigned long flags = 0; | ||
86 | |||
87 | if(w1_disable_irqs) local_irq_save(flags); | ||
88 | |||
82 | if (bit) { | 89 | if (bit) { |
83 | dev->bus_master->write_bit(dev->bus_master->data, 0); | 90 | dev->bus_master->write_bit(dev->bus_master->data, 0); |
84 | w1_delay(6); | 91 | w1_delay(6); |
@@ -90,6 +97,8 @@ static void w1_write_bit(struct w1_master *dev, int bit) | |||
90 | dev->bus_master->write_bit(dev->bus_master->data, 1); | 97 | dev->bus_master->write_bit(dev->bus_master->data, 1); |
91 | w1_delay(10); | 98 | w1_delay(10); |
92 | } | 99 | } |
100 | |||
101 | if(w1_disable_irqs) local_irq_restore(flags); | ||
93 | } | 102 | } |
94 | 103 | ||
95 | /** | 104 | /** |
@@ -158,7 +167,7 @@ EXPORT_SYMBOL_GPL(w1_write_8); | |||
158 | static u8 w1_read_bit(struct w1_master *dev) | 167 | static u8 w1_read_bit(struct w1_master *dev) |
159 | { | 168 | { |
160 | int result; | 169 | int result; |
161 | unsigned long flags; | 170 | unsigned long flags = 0; |
162 | 171 | ||
163 | /* sample timing is critical here */ | 172 | /* sample timing is critical here */ |
164 | local_irq_save(flags); | 173 | local_irq_save(flags); |
@@ -318,6 +327,9 @@ EXPORT_SYMBOL_GPL(w1_read_block); | |||
318 | int w1_reset_bus(struct w1_master *dev) | 327 | int w1_reset_bus(struct w1_master *dev) |
319 | { | 328 | { |
320 | int result; | 329 | int result; |
330 | unsigned long flags = 0; | ||
331 | |||
332 | if(w1_disable_irqs) local_irq_save(flags); | ||
321 | 333 | ||
322 | if (dev->bus_master->reset_bus) | 334 | if (dev->bus_master->reset_bus) |
323 | result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1; | 335 | result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1; |
@@ -330,19 +342,21 @@ int w1_reset_bus(struct w1_master *dev) | |||
330 | * cpu for such a short amount of time AND get it back in | 342 | * cpu for such a short amount of time AND get it back in |
331 | * the maximum amount of time. | 343 | * the maximum amount of time. |
332 | */ | 344 | */ |
333 | w1_delay(480); | 345 | w1_delay(500); |
334 | dev->bus_master->write_bit(dev->bus_master->data, 1); | 346 | dev->bus_master->write_bit(dev->bus_master->data, 1); |
335 | w1_delay(70); | 347 | w1_delay(70); |
336 | 348 | ||
337 | result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1; | 349 | result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1; |
338 | /* minmum 70 (above) + 410 = 480 us | 350 | /* minmum 70 (above) + 430 = 500 us |
339 | * There aren't any timing requirements between a reset and | 351 | * There aren't any timing requirements between a reset and |
340 | * the following transactions. Sleeping is safe here. | 352 | * the following transactions. Sleeping is safe here. |
341 | */ | 353 | */ |
342 | /* w1_delay(410); min required time */ | 354 | /* w1_delay(430); min required time */ |
343 | msleep(1); | 355 | msleep(1); |
344 | } | 356 | } |
345 | 357 | ||
358 | if(w1_disable_irqs) local_irq_restore(flags); | ||
359 | |||
346 | return result; | 360 | return result; |
347 | } | 361 | } |
348 | EXPORT_SYMBOL_GPL(w1_reset_bus); | 362 | EXPORT_SYMBOL_GPL(w1_reset_bus); |