diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:50:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-21 18:50:49 -0400 |
commit | 9a64388d83f6ef08dfff405a9d122e3dbcb6bf38 (patch) | |
tree | a77532ce4d6d56be6c6c7f405cd901a0184250fb /drivers | |
parent | e80ab411e589e00550e2e6e5a6a02d59cc730357 (diff) | |
parent | 14b3ca4022f050f8622ed282b734ddf445464583 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (202 commits)
[POWERPC] Fix compile breakage for 64-bit UP configs
[POWERPC] Define copy_siginfo_from_user32
[POWERPC] Add compat handler for PTRACE_GETSIGINFO
[POWERPC] i2c: Fix build breakage introduced by OF helpers
[POWERPC] Optimize fls64() on 64-bit processors
[POWERPC] irqtrace support for 64-bit powerpc
[POWERPC] Stacktrace support for lockdep
[POWERPC] Move stackframe definitions to common header
[POWERPC] Fix device-tree locking vs. interrupts
[POWERPC] Make pci_bus_to_host()'s struct pci_bus * argument const
[POWERPC] Remove unused __max_memory variable
[POWERPC] Simplify xics direct/lpar irq_host setup
[POWERPC] Use pseries_setup_i8259_cascade() in pseries_mpic_init_IRQ()
[POWERPC] Turn xics_setup_8259_cascade() into a generic pseries_setup_i8259_cascade()
[POWERPC] Move xics_setup_8259_cascade() into platforms/pseries/setup.c
[POWERPC] Use asm-generic/bitops/find.h in bitops.h
[POWERPC] 83xx: mpc8315 - fix USB UTMI Host setup
[POWERPC] 85xx: Fix the size of qe muram for MPC8568E
[POWERPC] 86xx: mpc86xx_hpcn - Temporarily accept old dts node identifier.
[POWERPC] 86xx: mark functions static, other minor cleanups
...
Diffstat (limited to 'drivers')
31 files changed, 1280 insertions, 361 deletions
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 41ca721d2523..ebfe038d859e 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -69,7 +69,7 @@ MODULE_LICENSE("GPL"); | |||
69 | enum { | 69 | enum { |
70 | PARTITION_SHIFT = 3, | 70 | PARTITION_SHIFT = 3, |
71 | MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS, | 71 | MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS, |
72 | MAX_DISK_NAME = sizeof(((struct gendisk *)0)->disk_name) | 72 | MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name) |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static DEFINE_SPINLOCK(viodasd_spinlock); | 75 | static DEFINE_SPINLOCK(viodasd_spinlock); |
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c index e74bb949c289..91cdb35a9204 100644 --- a/drivers/char/hvc_beat.c +++ b/drivers/char/hvc_beat.c | |||
@@ -78,8 +78,8 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt) | |||
78 | for (rest = cnt; rest > 0; rest -= nlen) { | 78 | for (rest = cnt; rest > 0; rest -= nlen) { |
79 | nlen = (rest > 16) ? 16 : rest; | 79 | nlen = (rest > 16) ? 16 : rest; |
80 | memcpy(kb, buf, nlen); | 80 | memcpy(kb, buf, nlen); |
81 | beat_put_term_char(vtermno, rest, kb[0], kb[1]); | 81 | beat_put_term_char(vtermno, nlen, kb[0], kb[1]); |
82 | rest -= nlen; | 82 | buf += nlen; |
83 | } | 83 | } |
84 | return cnt; | 84 | return cnt; |
85 | } | 85 | } |
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c index f577daedb630..aa7f7962a9a0 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.c +++ b/drivers/char/xilinx_hwicap/buffer_icap.c | |||
@@ -74,7 +74,7 @@ | |||
74 | 74 | ||
75 | /** | 75 | /** |
76 | * buffer_icap_get_status - Get the contents of the status register. | 76 | * buffer_icap_get_status - Get the contents of the status register. |
77 | * @base_address: is the base address of the device | 77 | * @drvdata: a pointer to the drvdata. |
78 | * | 78 | * |
79 | * The status register contains the ICAP status and the done bit. | 79 | * The status register contains the ICAP status and the done bit. |
80 | * | 80 | * |
@@ -88,9 +88,9 @@ | |||
88 | * D1 - Always 1 | 88 | * D1 - Always 1 |
89 | * D0 - Done bit | 89 | * D0 - Done bit |
90 | **/ | 90 | **/ |
91 | static inline u32 buffer_icap_get_status(void __iomem *base_address) | 91 | u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata) |
92 | { | 92 | { |
93 | return in_be32(base_address + XHI_STATUS_REG_OFFSET); | 93 | return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET); |
94 | } | 94 | } |
95 | 95 | ||
96 | /** | 96 | /** |
@@ -117,20 +117,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address, | |||
117 | **/ | 117 | **/ |
118 | static inline bool buffer_icap_busy(void __iomem *base_address) | 118 | static inline bool buffer_icap_busy(void __iomem *base_address) |
119 | { | 119 | { |
120 | return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED; | 120 | u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET); |
121 | } | 121 | return (status & 1) == XHI_NOT_FINISHED; |
122 | |||
123 | /** | ||
124 | * buffer_icap_busy - Return true if the icap device is not busy | ||
125 | * @base_address: is the base address of the device | ||
126 | * | ||
127 | * The queries the low order bit of the status register, which | ||
128 | * indicates whether the current configuration or readback operation | ||
129 | * has completed. | ||
130 | **/ | ||
131 | static inline bool buffer_icap_done(void __iomem *base_address) | ||
132 | { | ||
133 | return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED; | ||
134 | } | 122 | } |
135 | 123 | ||
136 | /** | 124 | /** |
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h index 03184959fa00..c5b1840906b2 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.h +++ b/drivers/char/xilinx_hwicap/buffer_icap.h | |||
@@ -44,8 +44,6 @@ | |||
44 | #include <asm/io.h> | 44 | #include <asm/io.h> |
45 | #include "xilinx_hwicap.h" | 45 | #include "xilinx_hwicap.h" |
46 | 46 | ||
47 | void buffer_icap_reset(struct hwicap_drvdata *drvdata); | ||
48 | |||
49 | /* Loads a partial bitstream from system memory. */ | 47 | /* Loads a partial bitstream from system memory. */ |
50 | int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, | 48 | int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, |
51 | u32 Size); | 49 | u32 Size); |
@@ -54,4 +52,7 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, | |||
54 | int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data, | 52 | int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data, |
55 | u32 Size); | 53 | u32 Size); |
56 | 54 | ||
55 | u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata); | ||
56 | void buffer_icap_reset(struct hwicap_drvdata *drvdata); | ||
57 | |||
57 | #endif | 58 | #endif |
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c index 6f45dbd47125..776b50528478 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.c +++ b/drivers/char/xilinx_hwicap/fifo_icap.c | |||
@@ -78,13 +78,6 @@ | |||
78 | #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */ | 78 | #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */ |
79 | #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */ | 79 | #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */ |
80 | 80 | ||
81 | /* Status Register (SR) */ | ||
82 | #define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */ | ||
83 | #define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */ | ||
84 | #define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */ | ||
85 | #define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */ | ||
86 | #define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */ | ||
87 | |||
88 | 81 | ||
89 | #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */ | 82 | #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */ |
90 | #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */ | 83 | #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */ |
@@ -152,13 +145,35 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata) | |||
152 | } | 145 | } |
153 | 146 | ||
154 | /** | 147 | /** |
148 | * fifo_icap_get_status - Get the contents of the status register. | ||
149 | * @drvdata: a pointer to the drvdata. | ||
150 | * | ||
151 | * The status register contains the ICAP status and the done bit. | ||
152 | * | ||
153 | * D8 - cfgerr | ||
154 | * D7 - dalign | ||
155 | * D6 - rip | ||
156 | * D5 - in_abort_l | ||
157 | * D4 - Always 1 | ||
158 | * D3 - Always 1 | ||
159 | * D2 - Always 1 | ||
160 | * D1 - Always 1 | ||
161 | * D0 - Done bit | ||
162 | **/ | ||
163 | u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata) | ||
164 | { | ||
165 | u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); | ||
166 | dev_dbg(drvdata->dev, "Getting status = %x\n", status); | ||
167 | return status; | ||
168 | } | ||
169 | |||
170 | /** | ||
155 | * fifo_icap_busy - Return true if the ICAP is still processing a transaction. | 171 | * fifo_icap_busy - Return true if the ICAP is still processing a transaction. |
156 | * @drvdata: a pointer to the drvdata. | 172 | * @drvdata: a pointer to the drvdata. |
157 | **/ | 173 | **/ |
158 | static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) | 174 | static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) |
159 | { | 175 | { |
160 | u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); | 176 | u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); |
161 | dev_dbg(drvdata->dev, "Getting status = %x\n", status); | ||
162 | return (status & XHI_SR_DONE_MASK) ? 0 : 1; | 177 | return (status & XHI_SR_DONE_MASK) ? 0 : 1; |
163 | } | 178 | } |
164 | 179 | ||
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h index 4d3068dd0405..ffabd3ba2bd8 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.h +++ b/drivers/char/xilinx_hwicap/fifo_icap.h | |||
@@ -56,6 +56,7 @@ int fifo_icap_set_configuration( | |||
56 | u32 *FrameBuffer, | 56 | u32 *FrameBuffer, |
57 | u32 NumWords); | 57 | u32 NumWords); |
58 | 58 | ||
59 | u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata); | ||
59 | void fifo_icap_reset(struct hwicap_drvdata *drvdata); | 60 | void fifo_icap_reset(struct hwicap_drvdata *drvdata); |
60 | void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata); | 61 | void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata); |
61 | 62 | ||
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 2284fa2a5a57..016f90567a52 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -36,7 +36,7 @@ | |||
36 | *****************************************************************************/ | 36 | *****************************************************************************/ |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * This is the code behind /dev/xilinx_icap -- it allows a user-space | 39 | * This is the code behind /dev/icap* -- it allows a user-space |
40 | * application to use the Xilinx ICAP subsystem. | 40 | * application to use the Xilinx ICAP subsystem. |
41 | * | 41 | * |
42 | * The following operations are possible: | 42 | * The following operations are possible: |
@@ -67,7 +67,7 @@ | |||
67 | * user-space application code that uses this device. The simplest | 67 | * user-space application code that uses this device. The simplest |
68 | * way to use this interface is simply: | 68 | * way to use this interface is simply: |
69 | * | 69 | * |
70 | * cp foo.bit /dev/xilinx_icap | 70 | * cp foo.bit /dev/icap0 |
71 | * | 71 | * |
72 | * Note that unless foo.bit is an appropriately constructed partial | 72 | * Note that unless foo.bit is an appropriately constructed partial |
73 | * bitstream, this has a high likelyhood of overwriting the design | 73 | * bitstream, this has a high likelyhood of overwriting the design |
@@ -105,18 +105,14 @@ | |||
105 | #include "buffer_icap.h" | 105 | #include "buffer_icap.h" |
106 | #include "fifo_icap.h" | 106 | #include "fifo_icap.h" |
107 | 107 | ||
108 | #define DRIVER_NAME "xilinx_icap" | 108 | #define DRIVER_NAME "icap" |
109 | 109 | ||
110 | #define HWICAP_REGS (0x10000) | 110 | #define HWICAP_REGS (0x10000) |
111 | 111 | ||
112 | /* dynamically allocate device number */ | 112 | #define XHWICAP_MAJOR 259 |
113 | static int xhwicap_major; | 113 | #define XHWICAP_MINOR 0 |
114 | static int xhwicap_minor; | ||
115 | #define HWICAP_DEVICES 1 | 114 | #define HWICAP_DEVICES 1 |
116 | 115 | ||
117 | module_param(xhwicap_major, int, S_IRUGO); | ||
118 | module_param(xhwicap_minor, int, S_IRUGO); | ||
119 | |||
120 | /* An array, which is set to true when the device is registered. */ | 116 | /* An array, which is set to true when the device is registered. */ |
121 | static bool probed_devices[HWICAP_DEVICES]; | 117 | static bool probed_devices[HWICAP_DEVICES]; |
122 | static struct mutex icap_sem; | 118 | static struct mutex icap_sem; |
@@ -250,8 +246,26 @@ static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, | |||
250 | * Create the data to be written to the ICAP. | 246 | * Create the data to be written to the ICAP. |
251 | */ | 247 | */ |
252 | buffer[index++] = XHI_DUMMY_PACKET; | 248 | buffer[index++] = XHI_DUMMY_PACKET; |
249 | buffer[index++] = XHI_NOOP_PACKET; | ||
253 | buffer[index++] = XHI_SYNC_PACKET; | 250 | buffer[index++] = XHI_SYNC_PACKET; |
254 | buffer[index++] = XHI_NOOP_PACKET; | 251 | buffer[index++] = XHI_NOOP_PACKET; |
252 | buffer[index++] = XHI_NOOP_PACKET; | ||
253 | |||
254 | /* | ||
255 | * Write the data to the FIFO and initiate the transfer of data present | ||
256 | * in the FIFO to the ICAP device. | ||
257 | */ | ||
258 | status = drvdata->config->set_configuration(drvdata, | ||
259 | &buffer[0], index); | ||
260 | if (status) | ||
261 | return status; | ||
262 | |||
263 | /* If the syncword was not found, then we need to start over. */ | ||
264 | status = drvdata->config->get_status(drvdata); | ||
265 | if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK) | ||
266 | return -EIO; | ||
267 | |||
268 | index = 0; | ||
255 | buffer[index++] = hwicap_type_1_read(reg) | 1; | 269 | buffer[index++] = hwicap_type_1_read(reg) | 1; |
256 | buffer[index++] = XHI_NOOP_PACKET; | 270 | buffer[index++] = XHI_NOOP_PACKET; |
257 | buffer[index++] = XHI_NOOP_PACKET; | 271 | buffer[index++] = XHI_NOOP_PACKET; |
@@ -587,7 +601,7 @@ static int __devinit hwicap_setup(struct device *dev, int id, | |||
587 | probed_devices[id] = 1; | 601 | probed_devices[id] = 1; |
588 | mutex_unlock(&icap_sem); | 602 | mutex_unlock(&icap_sem); |
589 | 603 | ||
590 | devt = MKDEV(xhwicap_major, xhwicap_minor + id); | 604 | devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id); |
591 | 605 | ||
592 | drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL); | 606 | drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL); |
593 | if (!drvdata) { | 607 | if (!drvdata) { |
@@ -664,12 +678,14 @@ static int __devinit hwicap_setup(struct device *dev, int id, | |||
664 | static struct hwicap_driver_config buffer_icap_config = { | 678 | static struct hwicap_driver_config buffer_icap_config = { |
665 | .get_configuration = buffer_icap_get_configuration, | 679 | .get_configuration = buffer_icap_get_configuration, |
666 | .set_configuration = buffer_icap_set_configuration, | 680 | .set_configuration = buffer_icap_set_configuration, |
681 | .get_status = buffer_icap_get_status, | ||
667 | .reset = buffer_icap_reset, | 682 | .reset = buffer_icap_reset, |
668 | }; | 683 | }; |
669 | 684 | ||
670 | static struct hwicap_driver_config fifo_icap_config = { | 685 | static struct hwicap_driver_config fifo_icap_config = { |
671 | .get_configuration = fifo_icap_get_configuration, | 686 | .get_configuration = fifo_icap_get_configuration, |
672 | .set_configuration = fifo_icap_set_configuration, | 687 | .set_configuration = fifo_icap_set_configuration, |
688 | .get_status = fifo_icap_get_status, | ||
673 | .reset = fifo_icap_reset, | 689 | .reset = fifo_icap_reset, |
674 | }; | 690 | }; |
675 | 691 | ||
@@ -690,7 +706,7 @@ static int __devexit hwicap_remove(struct device *dev) | |||
690 | dev_set_drvdata(dev, NULL); | 706 | dev_set_drvdata(dev, NULL); |
691 | 707 | ||
692 | mutex_lock(&icap_sem); | 708 | mutex_lock(&icap_sem); |
693 | probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0; | 709 | probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0; |
694 | mutex_unlock(&icap_sem); | 710 | mutex_unlock(&icap_sem); |
695 | return 0; /* success */ | 711 | return 0; /* success */ |
696 | } | 712 | } |
@@ -830,23 +846,12 @@ static int __init hwicap_module_init(void) | |||
830 | icap_class = class_create(THIS_MODULE, "xilinx_config"); | 846 | icap_class = class_create(THIS_MODULE, "xilinx_config"); |
831 | mutex_init(&icap_sem); | 847 | mutex_init(&icap_sem); |
832 | 848 | ||
833 | if (xhwicap_major) { | 849 | devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); |
834 | devt = MKDEV(xhwicap_major, xhwicap_minor); | 850 | retval = register_chrdev_region(devt, |
835 | retval = register_chrdev_region( | 851 | HWICAP_DEVICES, |
836 | devt, | 852 | DRIVER_NAME); |
837 | HWICAP_DEVICES, | 853 | if (retval < 0) |
838 | DRIVER_NAME); | 854 | return retval; |
839 | if (retval < 0) | ||
840 | return retval; | ||
841 | } else { | ||
842 | retval = alloc_chrdev_region(&devt, | ||
843 | xhwicap_minor, | ||
844 | HWICAP_DEVICES, | ||
845 | DRIVER_NAME); | ||
846 | if (retval < 0) | ||
847 | return retval; | ||
848 | xhwicap_major = MAJOR(devt); | ||
849 | } | ||
850 | 855 | ||
851 | retval = platform_driver_register(&hwicap_platform_driver); | 856 | retval = platform_driver_register(&hwicap_platform_driver); |
852 | 857 | ||
@@ -871,7 +876,7 @@ static int __init hwicap_module_init(void) | |||
871 | 876 | ||
872 | static void __exit hwicap_module_cleanup(void) | 877 | static void __exit hwicap_module_cleanup(void) |
873 | { | 878 | { |
874 | dev_t devt = MKDEV(xhwicap_major, xhwicap_minor); | 879 | dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); |
875 | 880 | ||
876 | class_destroy(icap_class); | 881 | class_destroy(icap_class); |
877 | 882 | ||
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index 405fee7e189b..1f9c8b082dbe 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h | |||
@@ -65,10 +65,27 @@ struct hwicap_drvdata { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct hwicap_driver_config { | 67 | struct hwicap_driver_config { |
68 | /* Read configuration data given by size into the data buffer. | ||
69 | Return 0 if successful. */ | ||
68 | int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data, | 70 | int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data, |
69 | u32 size); | 71 | u32 size); |
72 | /* Write configuration data given by size from the data buffer. | ||
73 | Return 0 if successful. */ | ||
70 | int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data, | 74 | int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data, |
71 | u32 size); | 75 | u32 size); |
76 | /* Get the status register, bit pattern given by: | ||
77 | * D8 - 0 = configuration error | ||
78 | * D7 - 1 = alignment found | ||
79 | * D6 - 1 = readback in progress | ||
80 | * D5 - 0 = abort in progress | ||
81 | * D4 - Always 1 | ||
82 | * D3 - Always 1 | ||
83 | * D2 - Always 1 | ||
84 | * D1 - Always 1 | ||
85 | * D0 - 1 = operation completed | ||
86 | */ | ||
87 | u32 (*get_status)(struct hwicap_drvdata *drvdata); | ||
88 | /* Reset the hw */ | ||
72 | void (*reset)(struct hwicap_drvdata *drvdata); | 89 | void (*reset)(struct hwicap_drvdata *drvdata); |
73 | }; | 90 | }; |
74 | 91 | ||
@@ -163,6 +180,13 @@ struct config_registers { | |||
163 | /* Constant to use for CRC check when CRC has been disabled */ | 180 | /* Constant to use for CRC check when CRC has been disabled */ |
164 | #define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL | 181 | #define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL |
165 | 182 | ||
183 | /* Meanings of the bits returned by get_status */ | ||
184 | #define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */ | ||
185 | #define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */ | ||
186 | #define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */ | ||
187 | #define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */ | ||
188 | #define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */ | ||
189 | |||
166 | /** | 190 | /** |
167 | * hwicap_type_1_read - Generates a Type 1 read packet header. | 191 | * hwicap_type_1_read - Generates a Type 1 read packet header. |
168 | * @reg: is the address of the register to be read back. | 192 | * @reg: is the address of the register to be read back. |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index b025dfe0b274..378b7aa63812 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -36,207 +36,12 @@ | |||
36 | #include <linux/mtd/partitions.h> | 36 | #include <linux/mtd/partitions.h> |
37 | 37 | ||
38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
39 | 39 | #include <asm/fsl_lbc.h> | |
40 | 40 | ||
41 | #define MAX_BANKS 8 | 41 | #define MAX_BANKS 8 |
42 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ | 42 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ |
43 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ | 43 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ |
44 | 44 | ||
45 | struct elbc_bank { | ||
46 | __be32 br; /**< Base Register */ | ||
47 | #define BR_BA 0xFFFF8000 | ||
48 | #define BR_BA_SHIFT 15 | ||
49 | #define BR_PS 0x00001800 | ||
50 | #define BR_PS_SHIFT 11 | ||
51 | #define BR_PS_8 0x00000800 /* Port Size 8 bit */ | ||
52 | #define BR_PS_16 0x00001000 /* Port Size 16 bit */ | ||
53 | #define BR_PS_32 0x00001800 /* Port Size 32 bit */ | ||
54 | #define BR_DECC 0x00000600 | ||
55 | #define BR_DECC_SHIFT 9 | ||
56 | #define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */ | ||
57 | #define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */ | ||
58 | #define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */ | ||
59 | #define BR_WP 0x00000100 | ||
60 | #define BR_WP_SHIFT 8 | ||
61 | #define BR_MSEL 0x000000E0 | ||
62 | #define BR_MSEL_SHIFT 5 | ||
63 | #define BR_MS_GPCM 0x00000000 /* GPCM */ | ||
64 | #define BR_MS_FCM 0x00000020 /* FCM */ | ||
65 | #define BR_MS_SDRAM 0x00000060 /* SDRAM */ | ||
66 | #define BR_MS_UPMA 0x00000080 /* UPMA */ | ||
67 | #define BR_MS_UPMB 0x000000A0 /* UPMB */ | ||
68 | #define BR_MS_UPMC 0x000000C0 /* UPMC */ | ||
69 | #define BR_V 0x00000001 | ||
70 | #define BR_V_SHIFT 0 | ||
71 | #define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V) | ||
72 | |||
73 | __be32 or; /**< Base Register */ | ||
74 | #define OR0 0x5004 | ||
75 | #define OR1 0x500C | ||
76 | #define OR2 0x5014 | ||
77 | #define OR3 0x501C | ||
78 | #define OR4 0x5024 | ||
79 | #define OR5 0x502C | ||
80 | #define OR6 0x5034 | ||
81 | #define OR7 0x503C | ||
82 | |||
83 | #define OR_FCM_AM 0xFFFF8000 | ||
84 | #define OR_FCM_AM_SHIFT 15 | ||
85 | #define OR_FCM_BCTLD 0x00001000 | ||
86 | #define OR_FCM_BCTLD_SHIFT 12 | ||
87 | #define OR_FCM_PGS 0x00000400 | ||
88 | #define OR_FCM_PGS_SHIFT 10 | ||
89 | #define OR_FCM_CSCT 0x00000200 | ||
90 | #define OR_FCM_CSCT_SHIFT 9 | ||
91 | #define OR_FCM_CST 0x00000100 | ||
92 | #define OR_FCM_CST_SHIFT 8 | ||
93 | #define OR_FCM_CHT 0x00000080 | ||
94 | #define OR_FCM_CHT_SHIFT 7 | ||
95 | #define OR_FCM_SCY 0x00000070 | ||
96 | #define OR_FCM_SCY_SHIFT 4 | ||
97 | #define OR_FCM_SCY_1 0x00000010 | ||
98 | #define OR_FCM_SCY_2 0x00000020 | ||
99 | #define OR_FCM_SCY_3 0x00000030 | ||
100 | #define OR_FCM_SCY_4 0x00000040 | ||
101 | #define OR_FCM_SCY_5 0x00000050 | ||
102 | #define OR_FCM_SCY_6 0x00000060 | ||
103 | #define OR_FCM_SCY_7 0x00000070 | ||
104 | #define OR_FCM_RST 0x00000008 | ||
105 | #define OR_FCM_RST_SHIFT 3 | ||
106 | #define OR_FCM_TRLX 0x00000004 | ||
107 | #define OR_FCM_TRLX_SHIFT 2 | ||
108 | #define OR_FCM_EHTR 0x00000002 | ||
109 | #define OR_FCM_EHTR_SHIFT 1 | ||
110 | }; | ||
111 | |||
112 | struct elbc_regs { | ||
113 | struct elbc_bank bank[8]; | ||
114 | u8 res0[0x28]; | ||
115 | __be32 mar; /**< UPM Address Register */ | ||
116 | u8 res1[0x4]; | ||
117 | __be32 mamr; /**< UPMA Mode Register */ | ||
118 | __be32 mbmr; /**< UPMB Mode Register */ | ||
119 | __be32 mcmr; /**< UPMC Mode Register */ | ||
120 | u8 res2[0x8]; | ||
121 | __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */ | ||
122 | __be32 mdr; /**< UPM Data Register */ | ||
123 | u8 res3[0x4]; | ||
124 | __be32 lsor; /**< Special Operation Initiation Register */ | ||
125 | __be32 lsdmr; /**< SDRAM Mode Register */ | ||
126 | u8 res4[0x8]; | ||
127 | __be32 lurt; /**< UPM Refresh Timer */ | ||
128 | __be32 lsrt; /**< SDRAM Refresh Timer */ | ||
129 | u8 res5[0x8]; | ||
130 | __be32 ltesr; /**< Transfer Error Status Register */ | ||
131 | #define LTESR_BM 0x80000000 | ||
132 | #define LTESR_FCT 0x40000000 | ||
133 | #define LTESR_PAR 0x20000000 | ||
134 | #define LTESR_WP 0x04000000 | ||
135 | #define LTESR_ATMW 0x00800000 | ||
136 | #define LTESR_ATMR 0x00400000 | ||
137 | #define LTESR_CS 0x00080000 | ||
138 | #define LTESR_CC 0x00000001 | ||
139 | #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) | ||
140 | __be32 ltedr; /**< Transfer Error Disable Register */ | ||
141 | __be32 lteir; /**< Transfer Error Interrupt Register */ | ||
142 | __be32 lteatr; /**< Transfer Error Attributes Register */ | ||
143 | __be32 ltear; /**< Transfer Error Address Register */ | ||
144 | u8 res6[0xC]; | ||
145 | __be32 lbcr; /**< Configuration Register */ | ||
146 | #define LBCR_LDIS 0x80000000 | ||
147 | #define LBCR_LDIS_SHIFT 31 | ||
148 | #define LBCR_BCTLC 0x00C00000 | ||
149 | #define LBCR_BCTLC_SHIFT 22 | ||
150 | #define LBCR_AHD 0x00200000 | ||
151 | #define LBCR_LPBSE 0x00020000 | ||
152 | #define LBCR_LPBSE_SHIFT 17 | ||
153 | #define LBCR_EPAR 0x00010000 | ||
154 | #define LBCR_EPAR_SHIFT 16 | ||
155 | #define LBCR_BMT 0x0000FF00 | ||
156 | #define LBCR_BMT_SHIFT 8 | ||
157 | #define LBCR_INIT 0x00040000 | ||
158 | __be32 lcrr; /**< Clock Ratio Register */ | ||
159 | #define LCRR_DBYP 0x80000000 | ||
160 | #define LCRR_DBYP_SHIFT 31 | ||
161 | #define LCRR_BUFCMDC 0x30000000 | ||
162 | #define LCRR_BUFCMDC_SHIFT 28 | ||
163 | #define LCRR_ECL 0x03000000 | ||
164 | #define LCRR_ECL_SHIFT 24 | ||
165 | #define LCRR_EADC 0x00030000 | ||
166 | #define LCRR_EADC_SHIFT 16 | ||
167 | #define LCRR_CLKDIV 0x0000000F | ||
168 | #define LCRR_CLKDIV_SHIFT 0 | ||
169 | u8 res7[0x8]; | ||
170 | __be32 fmr; /**< Flash Mode Register */ | ||
171 | #define FMR_CWTO 0x0000F000 | ||
172 | #define FMR_CWTO_SHIFT 12 | ||
173 | #define FMR_BOOT 0x00000800 | ||
174 | #define FMR_ECCM 0x00000100 | ||
175 | #define FMR_AL 0x00000030 | ||
176 | #define FMR_AL_SHIFT 4 | ||
177 | #define FMR_OP 0x00000003 | ||
178 | #define FMR_OP_SHIFT 0 | ||
179 | __be32 fir; /**< Flash Instruction Register */ | ||
180 | #define FIR_OP0 0xF0000000 | ||
181 | #define FIR_OP0_SHIFT 28 | ||
182 | #define FIR_OP1 0x0F000000 | ||
183 | #define FIR_OP1_SHIFT 24 | ||
184 | #define FIR_OP2 0x00F00000 | ||
185 | #define FIR_OP2_SHIFT 20 | ||
186 | #define FIR_OP3 0x000F0000 | ||
187 | #define FIR_OP3_SHIFT 16 | ||
188 | #define FIR_OP4 0x0000F000 | ||
189 | #define FIR_OP4_SHIFT 12 | ||
190 | #define FIR_OP5 0x00000F00 | ||
191 | #define FIR_OP5_SHIFT 8 | ||
192 | #define FIR_OP6 0x000000F0 | ||
193 | #define FIR_OP6_SHIFT 4 | ||
194 | #define FIR_OP7 0x0000000F | ||
195 | #define FIR_OP7_SHIFT 0 | ||
196 | #define FIR_OP_NOP 0x0 /* No operation and end of sequence */ | ||
197 | #define FIR_OP_CA 0x1 /* Issue current column address */ | ||
198 | #define FIR_OP_PA 0x2 /* Issue current block+page address */ | ||
199 | #define FIR_OP_UA 0x3 /* Issue user defined address */ | ||
200 | #define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */ | ||
201 | #define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */ | ||
202 | #define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */ | ||
203 | #define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */ | ||
204 | #define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */ | ||
205 | #define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */ | ||
206 | #define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */ | ||
207 | #define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */ | ||
208 | #define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */ | ||
209 | #define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */ | ||
210 | #define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */ | ||
211 | #define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */ | ||
212 | __be32 fcr; /**< Flash Command Register */ | ||
213 | #define FCR_CMD0 0xFF000000 | ||
214 | #define FCR_CMD0_SHIFT 24 | ||
215 | #define FCR_CMD1 0x00FF0000 | ||
216 | #define FCR_CMD1_SHIFT 16 | ||
217 | #define FCR_CMD2 0x0000FF00 | ||
218 | #define FCR_CMD2_SHIFT 8 | ||
219 | #define FCR_CMD3 0x000000FF | ||
220 | #define FCR_CMD3_SHIFT 0 | ||
221 | __be32 fbar; /**< Flash Block Address Register */ | ||
222 | #define FBAR_BLK 0x00FFFFFF | ||
223 | __be32 fpar; /**< Flash Page Address Register */ | ||
224 | #define FPAR_SP_PI 0x00007C00 | ||
225 | #define FPAR_SP_PI_SHIFT 10 | ||
226 | #define FPAR_SP_MS 0x00000200 | ||
227 | #define FPAR_SP_CI 0x000001FF | ||
228 | #define FPAR_SP_CI_SHIFT 0 | ||
229 | #define FPAR_LP_PI 0x0003F000 | ||
230 | #define FPAR_LP_PI_SHIFT 12 | ||
231 | #define FPAR_LP_MS 0x00000800 | ||
232 | #define FPAR_LP_CI 0x000007FF | ||
233 | #define FPAR_LP_CI_SHIFT 0 | ||
234 | __be32 fbcr; /**< Flash Byte Count Register */ | ||
235 | #define FBCR_BC 0x00000FFF | ||
236 | u8 res11[0x8]; | ||
237 | u8 res8[0xF00]; | ||
238 | }; | ||
239 | |||
240 | struct fsl_elbc_ctrl; | 45 | struct fsl_elbc_ctrl; |
241 | 46 | ||
242 | /* mtd information per set */ | 47 | /* mtd information per set */ |
@@ -261,7 +66,7 @@ struct fsl_elbc_ctrl { | |||
261 | 66 | ||
262 | /* device info */ | 67 | /* device info */ |
263 | struct device *dev; | 68 | struct device *dev; |
264 | struct elbc_regs __iomem *regs; | 69 | struct fsl_lbc_regs __iomem *regs; |
265 | int irq; | 70 | int irq; |
266 | wait_queue_head_t irq_wait; | 71 | wait_queue_head_t irq_wait; |
267 | unsigned int irq_status; /* status read from LTESR by irq handler */ | 72 | unsigned int irq_status; /* status read from LTESR by irq handler */ |
@@ -322,7 +127,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
322 | struct nand_chip *chip = mtd->priv; | 127 | struct nand_chip *chip = mtd->priv; |
323 | struct fsl_elbc_mtd *priv = chip->priv; | 128 | struct fsl_elbc_mtd *priv = chip->priv; |
324 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 129 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
325 | struct elbc_regs __iomem *lbc = ctrl->regs; | 130 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
326 | int buf_num; | 131 | int buf_num; |
327 | 132 | ||
328 | ctrl->page = page_addr; | 133 | ctrl->page = page_addr; |
@@ -363,7 +168,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
363 | struct nand_chip *chip = mtd->priv; | 168 | struct nand_chip *chip = mtd->priv; |
364 | struct fsl_elbc_mtd *priv = chip->priv; | 169 | struct fsl_elbc_mtd *priv = chip->priv; |
365 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 170 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
366 | struct elbc_regs __iomem *lbc = ctrl->regs; | 171 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
367 | 172 | ||
368 | /* Setup the FMR[OP] to execute without write protection */ | 173 | /* Setup the FMR[OP] to execute without write protection */ |
369 | out_be32(&lbc->fmr, priv->fmr | 3); | 174 | out_be32(&lbc->fmr, priv->fmr | 3); |
@@ -406,7 +211,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob) | |||
406 | { | 211 | { |
407 | struct fsl_elbc_mtd *priv = chip->priv; | 212 | struct fsl_elbc_mtd *priv = chip->priv; |
408 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 213 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
409 | struct elbc_regs __iomem *lbc = ctrl->regs; | 214 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
410 | 215 | ||
411 | if (priv->page_size) { | 216 | if (priv->page_size) { |
412 | out_be32(&lbc->fir, | 217 | out_be32(&lbc->fir, |
@@ -439,7 +244,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
439 | struct nand_chip *chip = mtd->priv; | 244 | struct nand_chip *chip = mtd->priv; |
440 | struct fsl_elbc_mtd *priv = chip->priv; | 245 | struct fsl_elbc_mtd *priv = chip->priv; |
441 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 246 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
442 | struct elbc_regs __iomem *lbc = ctrl->regs; | 247 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
443 | 248 | ||
444 | ctrl->use_mdr = 0; | 249 | ctrl->use_mdr = 0; |
445 | 250 | ||
@@ -775,7 +580,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
775 | { | 580 | { |
776 | struct fsl_elbc_mtd *priv = chip->priv; | 581 | struct fsl_elbc_mtd *priv = chip->priv; |
777 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 582 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
778 | struct elbc_regs __iomem *lbc = ctrl->regs; | 583 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
779 | 584 | ||
780 | if (ctrl->status != LTESR_CC) | 585 | if (ctrl->status != LTESR_CC) |
781 | return NAND_STATUS_FAIL; | 586 | return NAND_STATUS_FAIL; |
@@ -807,7 +612,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
807 | struct nand_chip *chip = mtd->priv; | 612 | struct nand_chip *chip = mtd->priv; |
808 | struct fsl_elbc_mtd *priv = chip->priv; | 613 | struct fsl_elbc_mtd *priv = chip->priv; |
809 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 614 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
810 | struct elbc_regs __iomem *lbc = ctrl->regs; | 615 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
811 | unsigned int al; | 616 | unsigned int al; |
812 | 617 | ||
813 | /* calculate FMR Address Length field */ | 618 | /* calculate FMR Address Length field */ |
@@ -922,7 +727,7 @@ static void fsl_elbc_write_page(struct mtd_info *mtd, | |||
922 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | 727 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
923 | { | 728 | { |
924 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 729 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
925 | struct elbc_regs __iomem *lbc = ctrl->regs; | 730 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
926 | struct nand_chip *chip = &priv->chip; | 731 | struct nand_chip *chip = &priv->chip; |
927 | 732 | ||
928 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); | 733 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); |
@@ -986,7 +791,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |||
986 | static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | 791 | static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, |
987 | struct device_node *node) | 792 | struct device_node *node) |
988 | { | 793 | { |
989 | struct elbc_regs __iomem *lbc = ctrl->regs; | 794 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
990 | struct fsl_elbc_mtd *priv; | 795 | struct fsl_elbc_mtd *priv; |
991 | struct resource res; | 796 | struct resource res; |
992 | #ifdef CONFIG_MTD_PARTITIONS | 797 | #ifdef CONFIG_MTD_PARTITIONS |
@@ -1083,7 +888,7 @@ err: | |||
1083 | 888 | ||
1084 | static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) | 889 | static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) |
1085 | { | 890 | { |
1086 | struct elbc_regs __iomem *lbc = ctrl->regs; | 891 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
1087 | 892 | ||
1088 | /* clear event registers */ | 893 | /* clear event registers */ |
1089 | setbits32(&lbc->ltesr, LTESR_NAND_MASK); | 894 | setbits32(&lbc->ltesr, LTESR_NAND_MASK); |
@@ -1128,7 +933,7 @@ static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev) | |||
1128 | static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) | 933 | static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) |
1129 | { | 934 | { |
1130 | struct fsl_elbc_ctrl *ctrl = data; | 935 | struct fsl_elbc_ctrl *ctrl = data; |
1131 | struct elbc_regs __iomem *lbc = ctrl->regs; | 936 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
1132 | __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK; | 937 | __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK; |
1133 | 938 | ||
1134 | if (status) { | 939 | if (status) { |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 4d71729e85e5..2f1f3f2739fd 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -218,7 +218,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o | |||
218 | obj-$(CONFIG_BFIN_MAC) += bfin_mac.o | 218 | obj-$(CONFIG_BFIN_MAC) += bfin_mac.o |
219 | obj-$(CONFIG_DM9000) += dm9000.o | 219 | obj-$(CONFIG_DM9000) += dm9000.o |
220 | obj-$(CONFIG_FEC_8XX) += fec_8xx/ | 220 | obj-$(CONFIG_FEC_8XX) += fec_8xx/ |
221 | obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o | 221 | obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o |
222 | pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o | ||
222 | obj-$(CONFIG_MLX4_CORE) += mlx4/ | 223 | obj-$(CONFIG_MLX4_CORE) += mlx4/ |
223 | obj-$(CONFIG_ENC28J60) += enc28j60.o | 224 | obj-$(CONFIG_ENC28J60) += enc28j60.o |
224 | 225 | ||
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 58d3bb622da6..b8d0639c1cdf 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c | |||
@@ -308,7 +308,8 @@ static void veth_complete_allocation(void *parm, int number) | |||
308 | 308 | ||
309 | static int veth_allocate_events(HvLpIndex rlp, int number) | 309 | static int veth_allocate_events(HvLpIndex rlp, int number) |
310 | { | 310 | { |
311 | struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 }; | 311 | struct veth_allocation vc = |
312 | { COMPLETION_INITIALIZER_ONSTACK(vc.c), 0 }; | ||
312 | 313 | ||
313 | mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan, | 314 | mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan, |
314 | sizeof(struct veth_lpevent), number, | 315 | sizeof(struct veth_lpevent), number, |
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index bcd7f9814ed8..3b2a6c598088 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c | |||
@@ -55,15 +55,10 @@ | |||
55 | * - Multiqueue RX/TX | 55 | * - Multiqueue RX/TX |
56 | */ | 56 | */ |
57 | 57 | ||
58 | |||
59 | /* Must be a power of two */ | ||
60 | #define RX_RING_SIZE 2048 | ||
61 | #define TX_RING_SIZE 4096 | ||
62 | |||
63 | #define LRO_MAX_AGGR 64 | 58 | #define LRO_MAX_AGGR 64 |
64 | 59 | ||
65 | #define PE_MIN_MTU 64 | 60 | #define PE_MIN_MTU 64 |
66 | #define PE_MAX_MTU 1500 | 61 | #define PE_MAX_MTU 9000 |
67 | #define PE_DEF_MTU ETH_DATA_LEN | 62 | #define PE_DEF_MTU ETH_DATA_LEN |
68 | 63 | ||
69 | #define DEFAULT_MSG_ENABLE \ | 64 | #define DEFAULT_MSG_ENABLE \ |
@@ -76,16 +71,6 @@ | |||
76 | NETIF_MSG_RX_ERR | \ | 71 | NETIF_MSG_RX_ERR | \ |
77 | NETIF_MSG_TX_ERR) | 72 | NETIF_MSG_TX_ERR) |
78 | 73 | ||
79 | #define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)]) | ||
80 | #define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)]) | ||
81 | #define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)]) | ||
82 | #define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)]) | ||
83 | #define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)]) | ||
84 | |||
85 | #define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \ | ||
86 | & ((ring)->size - 1)) | ||
87 | #define RING_AVAIL(ring) ((ring->size) - RING_USED(ring)) | ||
88 | |||
89 | MODULE_LICENSE("GPL"); | 74 | MODULE_LICENSE("GPL"); |
90 | MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); | 75 | MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); |
91 | MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver"); | 76 | MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver"); |
@@ -94,6 +79,8 @@ static int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */ | |||
94 | module_param(debug, int, 0); | 79 | module_param(debug, int, 0); |
95 | MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value"); | 80 | MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value"); |
96 | 81 | ||
82 | extern const struct ethtool_ops pasemi_mac_ethtool_ops; | ||
83 | |||
97 | static int translation_enabled(void) | 84 | static int translation_enabled(void) |
98 | { | 85 | { |
99 | #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE) | 86 | #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE) |
@@ -322,6 +309,104 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac, | |||
322 | return (nfrags + 3) & ~1; | 309 | return (nfrags + 3) & ~1; |
323 | } | 310 | } |
324 | 311 | ||
312 | static struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac) | ||
313 | { | ||
314 | struct pasemi_mac_csring *ring; | ||
315 | u32 val; | ||
316 | unsigned int cfg; | ||
317 | int chno; | ||
318 | |||
319 | ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring), | ||
320 | offsetof(struct pasemi_mac_csring, chan)); | ||
321 | |||
322 | if (!ring) { | ||
323 | dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n"); | ||
324 | goto out_chan; | ||
325 | } | ||
326 | |||
327 | chno = ring->chan.chno; | ||
328 | |||
329 | ring->size = CS_RING_SIZE; | ||
330 | ring->next_to_fill = 0; | ||
331 | |||
332 | /* Allocate descriptors */ | ||
333 | if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE)) | ||
334 | goto out_ring_desc; | ||
335 | |||
336 | write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno), | ||
337 | PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma)); | ||
338 | val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32); | ||
339 | val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3); | ||
340 | |||
341 | write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val); | ||
342 | |||
343 | ring->events[0] = pasemi_dma_alloc_flag(); | ||
344 | ring->events[1] = pasemi_dma_alloc_flag(); | ||
345 | if (ring->events[0] < 0 || ring->events[1] < 0) | ||
346 | goto out_flags; | ||
347 | |||
348 | pasemi_dma_clear_flag(ring->events[0]); | ||
349 | pasemi_dma_clear_flag(ring->events[1]); | ||
350 | |||
351 | ring->fun = pasemi_dma_alloc_fun(); | ||
352 | if (ring->fun < 0) | ||
353 | goto out_fun; | ||
354 | |||
355 | cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP | | ||
356 | PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) | | ||
357 | PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ; | ||
358 | |||
359 | if (translation_enabled()) | ||
360 | cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR; | ||
361 | |||
362 | write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg); | ||
363 | |||
364 | /* enable channel */ | ||
365 | pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ | | ||
366 | PAS_DMA_TXCHAN_TCMDSTA_DB | | ||
367 | PAS_DMA_TXCHAN_TCMDSTA_DE | | ||
368 | PAS_DMA_TXCHAN_TCMDSTA_DA); | ||
369 | |||
370 | return ring; | ||
371 | |||
372 | out_fun: | ||
373 | out_flags: | ||
374 | if (ring->events[0] >= 0) | ||
375 | pasemi_dma_free_flag(ring->events[0]); | ||
376 | if (ring->events[1] >= 0) | ||
377 | pasemi_dma_free_flag(ring->events[1]); | ||
378 | pasemi_dma_free_ring(&ring->chan); | ||
379 | out_ring_desc: | ||
380 | pasemi_dma_free_chan(&ring->chan); | ||
381 | out_chan: | ||
382 | |||
383 | return NULL; | ||
384 | } | ||
385 | |||
386 | static void pasemi_mac_setup_csrings(struct pasemi_mac *mac) | ||
387 | { | ||
388 | int i; | ||
389 | mac->cs[0] = pasemi_mac_setup_csring(mac); | ||
390 | if (mac->type == MAC_TYPE_XAUI) | ||
391 | mac->cs[1] = pasemi_mac_setup_csring(mac); | ||
392 | else | ||
393 | mac->cs[1] = 0; | ||
394 | |||
395 | for (i = 0; i < MAX_CS; i++) | ||
396 | if (mac->cs[i]) | ||
397 | mac->num_cs++; | ||
398 | } | ||
399 | |||
400 | static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring) | ||
401 | { | ||
402 | pasemi_dma_stop_chan(&csring->chan); | ||
403 | pasemi_dma_free_flag(csring->events[0]); | ||
404 | pasemi_dma_free_flag(csring->events[1]); | ||
405 | pasemi_dma_free_ring(&csring->chan); | ||
406 | pasemi_dma_free_chan(&csring->chan); | ||
407 | pasemi_dma_free_fun(csring->fun); | ||
408 | } | ||
409 | |||
325 | static int pasemi_mac_setup_rx_resources(const struct net_device *dev) | 410 | static int pasemi_mac_setup_rx_resources(const struct net_device *dev) |
326 | { | 411 | { |
327 | struct pasemi_mac_rxring *ring; | 412 | struct pasemi_mac_rxring *ring; |
@@ -445,7 +530,7 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev) | |||
445 | cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE | | 530 | cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE | |
446 | PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) | | 531 | PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) | |
447 | PAS_DMA_TXCHAN_CFG_UP | | 532 | PAS_DMA_TXCHAN_CFG_UP | |
448 | PAS_DMA_TXCHAN_CFG_WT(2); | 533 | PAS_DMA_TXCHAN_CFG_WT(4); |
449 | 534 | ||
450 | if (translation_enabled()) | 535 | if (translation_enabled()) |
451 | cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR; | 536 | cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR; |
@@ -810,13 +895,21 @@ restart: | |||
810 | u64 mactx = TX_DESC(txring, i); | 895 | u64 mactx = TX_DESC(txring, i); |
811 | struct sk_buff *skb; | 896 | struct sk_buff *skb; |
812 | 897 | ||
813 | skb = TX_DESC_INFO(txring, i+1).skb; | ||
814 | nr_frags = TX_DESC_INFO(txring, i).dma; | ||
815 | |||
816 | if ((mactx & XCT_MACTX_E) || | 898 | if ((mactx & XCT_MACTX_E) || |
817 | (*chan->status & PAS_STATUS_ERROR)) | 899 | (*chan->status & PAS_STATUS_ERROR)) |
818 | pasemi_mac_tx_error(mac, mactx); | 900 | pasemi_mac_tx_error(mac, mactx); |
819 | 901 | ||
902 | /* Skip over control descriptors */ | ||
903 | if (!(mactx & XCT_MACTX_LLEN_M)) { | ||
904 | TX_DESC(txring, i) = 0; | ||
905 | TX_DESC(txring, i+1) = 0; | ||
906 | buf_count = 2; | ||
907 | continue; | ||
908 | } | ||
909 | |||
910 | skb = TX_DESC_INFO(txring, i+1).skb; | ||
911 | nr_frags = TX_DESC_INFO(txring, i).dma; | ||
912 | |||
820 | if (unlikely(mactx & XCT_MACTX_O)) | 913 | if (unlikely(mactx & XCT_MACTX_O)) |
821 | /* Not yet transmitted */ | 914 | /* Not yet transmitted */ |
822 | break; | 915 | break; |
@@ -1041,13 +1134,7 @@ static int pasemi_mac_open(struct net_device *dev) | |||
1041 | { | 1134 | { |
1042 | struct pasemi_mac *mac = netdev_priv(dev); | 1135 | struct pasemi_mac *mac = netdev_priv(dev); |
1043 | unsigned int flags; | 1136 | unsigned int flags; |
1044 | int ret; | 1137 | int i, ret; |
1045 | |||
1046 | /* enable rx section */ | ||
1047 | write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN); | ||
1048 | |||
1049 | /* enable tx section */ | ||
1050 | write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN); | ||
1051 | 1138 | ||
1052 | flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) | | 1139 | flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) | |
1053 | PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) | | 1140 | PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) | |
@@ -1064,6 +1151,19 @@ static int pasemi_mac_open(struct net_device *dev) | |||
1064 | if (!mac->tx) | 1151 | if (!mac->tx) |
1065 | goto out_tx_ring; | 1152 | goto out_tx_ring; |
1066 | 1153 | ||
1154 | /* We might already have allocated rings in case mtu was changed | ||
1155 | * before interface was brought up. | ||
1156 | */ | ||
1157 | if (dev->mtu > 1500 && !mac->num_cs) { | ||
1158 | pasemi_mac_setup_csrings(mac); | ||
1159 | if (!mac->num_cs) | ||
1160 | goto out_tx_ring; | ||
1161 | } | ||
1162 | |||
1163 | /* Zero out rmon counters */ | ||
1164 | for (i = 0; i < 32; i++) | ||
1165 | write_mac_reg(mac, PAS_MAC_RMON(i), 0); | ||
1166 | |||
1067 | /* 0x3ff with 33MHz clock is about 31us */ | 1167 | /* 0x3ff with 33MHz clock is about 31us */ |
1068 | write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG, | 1168 | write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG, |
1069 | PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff)); | 1169 | PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff)); |
@@ -1247,7 +1347,7 @@ static int pasemi_mac_close(struct net_device *dev) | |||
1247 | { | 1347 | { |
1248 | struct pasemi_mac *mac = netdev_priv(dev); | 1348 | struct pasemi_mac *mac = netdev_priv(dev); |
1249 | unsigned int sta; | 1349 | unsigned int sta; |
1250 | int rxch, txch; | 1350 | int rxch, txch, i; |
1251 | 1351 | ||
1252 | rxch = rx_ring(mac)->chan.chno; | 1352 | rxch = rx_ring(mac)->chan.chno; |
1253 | txch = tx_ring(mac)->chan.chno; | 1353 | txch = tx_ring(mac)->chan.chno; |
@@ -1292,6 +1392,13 @@ static int pasemi_mac_close(struct net_device *dev) | |||
1292 | free_irq(mac->tx->chan.irq, mac->tx); | 1392 | free_irq(mac->tx->chan.irq, mac->tx); |
1293 | free_irq(mac->rx->chan.irq, mac->rx); | 1393 | free_irq(mac->rx->chan.irq, mac->rx); |
1294 | 1394 | ||
1395 | for (i = 0; i < mac->num_cs; i++) { | ||
1396 | pasemi_mac_free_csring(mac->cs[i]); | ||
1397 | mac->cs[i] = NULL; | ||
1398 | } | ||
1399 | |||
1400 | mac->num_cs = 0; | ||
1401 | |||
1295 | /* Free resources */ | 1402 | /* Free resources */ |
1296 | pasemi_mac_free_rx_resources(mac); | 1403 | pasemi_mac_free_rx_resources(mac); |
1297 | pasemi_mac_free_tx_resources(mac); | 1404 | pasemi_mac_free_tx_resources(mac); |
@@ -1299,35 +1406,113 @@ static int pasemi_mac_close(struct net_device *dev) | |||
1299 | return 0; | 1406 | return 0; |
1300 | } | 1407 | } |
1301 | 1408 | ||
1409 | static void pasemi_mac_queue_csdesc(const struct sk_buff *skb, | ||
1410 | const dma_addr_t *map, | ||
1411 | const unsigned int *map_size, | ||
1412 | struct pasemi_mac_txring *txring, | ||
1413 | struct pasemi_mac_csring *csring) | ||
1414 | { | ||
1415 | u64 fund; | ||
1416 | dma_addr_t cs_dest; | ||
1417 | const int nh_off = skb_network_offset(skb); | ||
1418 | const int nh_len = skb_network_header_len(skb); | ||
1419 | const int nfrags = skb_shinfo(skb)->nr_frags; | ||
1420 | int cs_size, i, fill, hdr, cpyhdr, evt; | ||
1421 | dma_addr_t csdma; | ||
1422 | |||
1423 | fund = XCT_FUN_ST | XCT_FUN_RR_8BRES | | ||
1424 | XCT_FUN_O | XCT_FUN_FUN(csring->fun) | | ||
1425 | XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) | | ||
1426 | XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE; | ||
1427 | |||
1428 | switch (ip_hdr(skb)->protocol) { | ||
1429 | case IPPROTO_TCP: | ||
1430 | fund |= XCT_FUN_SIG_TCP4; | ||
1431 | /* TCP checksum is 16 bytes into the header */ | ||
1432 | cs_dest = map[0] + skb_transport_offset(skb) + 16; | ||
1433 | break; | ||
1434 | case IPPROTO_UDP: | ||
1435 | fund |= XCT_FUN_SIG_UDP4; | ||
1436 | /* UDP checksum is 6 bytes into the header */ | ||
1437 | cs_dest = map[0] + skb_transport_offset(skb) + 6; | ||
1438 | break; | ||
1439 | default: | ||
1440 | BUG(); | ||
1441 | } | ||
1442 | |||
1443 | /* Do the checksum offloaded */ | ||
1444 | fill = csring->next_to_fill; | ||
1445 | hdr = fill; | ||
1446 | |||
1447 | CS_DESC(csring, fill++) = fund; | ||
1448 | /* Room for 8BRES. Checksum result is really 2 bytes into it */ | ||
1449 | csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2; | ||
1450 | CS_DESC(csring, fill++) = 0; | ||
1451 | |||
1452 | CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off); | ||
1453 | for (i = 1; i <= nfrags; i++) | ||
1454 | CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]); | ||
1455 | |||
1456 | fill += i; | ||
1457 | if (fill & 1) | ||
1458 | fill++; | ||
1459 | |||
1460 | /* Copy the result into the TCP packet */ | ||
1461 | cpyhdr = fill; | ||
1462 | CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) | | ||
1463 | XCT_FUN_LLEN(2) | XCT_FUN_SE; | ||
1464 | CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T; | ||
1465 | CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma); | ||
1466 | fill++; | ||
1467 | |||
1468 | evt = !csring->last_event; | ||
1469 | csring->last_event = evt; | ||
1470 | |||
1471 | /* Event handshaking with MAC TX */ | ||
1472 | CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | | ||
1473 | CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]); | ||
1474 | CS_DESC(csring, fill++) = 0; | ||
1475 | CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | | ||
1476 | CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]); | ||
1477 | CS_DESC(csring, fill++) = 0; | ||
1478 | csring->next_to_fill = fill & (CS_RING_SIZE-1); | ||
1479 | |||
1480 | cs_size = fill - hdr; | ||
1481 | write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1); | ||
1482 | |||
1483 | /* TX-side event handshaking */ | ||
1484 | fill = txring->next_to_fill; | ||
1485 | TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | | ||
1486 | CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]); | ||
1487 | TX_DESC(txring, fill++) = 0; | ||
1488 | TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | | ||
1489 | CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]); | ||
1490 | TX_DESC(txring, fill++) = 0; | ||
1491 | txring->next_to_fill = fill; | ||
1492 | |||
1493 | write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2); | ||
1494 | |||
1495 | return; | ||
1496 | } | ||
1497 | |||
1302 | static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) | 1498 | static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) |
1303 | { | 1499 | { |
1304 | struct pasemi_mac *mac = netdev_priv(dev); | 1500 | struct pasemi_mac * const mac = netdev_priv(dev); |
1305 | struct pasemi_mac_txring *txring; | 1501 | struct pasemi_mac_txring * const txring = tx_ring(mac); |
1306 | u64 dflags, mactx; | 1502 | struct pasemi_mac_csring *csring; |
1503 | u64 dflags = 0; | ||
1504 | u64 mactx; | ||
1307 | dma_addr_t map[MAX_SKB_FRAGS+1]; | 1505 | dma_addr_t map[MAX_SKB_FRAGS+1]; |
1308 | unsigned int map_size[MAX_SKB_FRAGS+1]; | 1506 | unsigned int map_size[MAX_SKB_FRAGS+1]; |
1309 | unsigned long flags; | 1507 | unsigned long flags; |
1310 | int i, nfrags; | 1508 | int i, nfrags; |
1311 | int fill; | 1509 | int fill; |
1510 | const int nh_off = skb_network_offset(skb); | ||
1511 | const int nh_len = skb_network_header_len(skb); | ||
1312 | 1512 | ||
1313 | dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD; | 1513 | prefetch(&txring->ring_info); |
1314 | |||
1315 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | ||
1316 | const unsigned char *nh = skb_network_header(skb); | ||
1317 | 1514 | ||
1318 | switch (ip_hdr(skb)->protocol) { | 1515 | dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD; |
1319 | case IPPROTO_TCP: | ||
1320 | dflags |= XCT_MACTX_CSUM_TCP; | ||
1321 | dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2); | ||
1322 | dflags |= XCT_MACTX_IPO(nh - skb->data); | ||
1323 | break; | ||
1324 | case IPPROTO_UDP: | ||
1325 | dflags |= XCT_MACTX_CSUM_UDP; | ||
1326 | dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2); | ||
1327 | dflags |= XCT_MACTX_IPO(nh - skb->data); | ||
1328 | break; | ||
1329 | } | ||
1330 | } | ||
1331 | 1516 | ||
1332 | nfrags = skb_shinfo(skb)->nr_frags; | 1517 | nfrags = skb_shinfo(skb)->nr_frags; |
1333 | 1518 | ||
@@ -1350,24 +1535,46 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) | |||
1350 | } | 1535 | } |
1351 | } | 1536 | } |
1352 | 1537 | ||
1353 | mactx = dflags | XCT_MACTX_LLEN(skb->len); | 1538 | if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) { |
1539 | switch (ip_hdr(skb)->protocol) { | ||
1540 | case IPPROTO_TCP: | ||
1541 | dflags |= XCT_MACTX_CSUM_TCP; | ||
1542 | dflags |= XCT_MACTX_IPH(nh_len >> 2); | ||
1543 | dflags |= XCT_MACTX_IPO(nh_off); | ||
1544 | break; | ||
1545 | case IPPROTO_UDP: | ||
1546 | dflags |= XCT_MACTX_CSUM_UDP; | ||
1547 | dflags |= XCT_MACTX_IPH(nh_len >> 2); | ||
1548 | dflags |= XCT_MACTX_IPO(nh_off); | ||
1549 | break; | ||
1550 | default: | ||
1551 | WARN_ON(1); | ||
1552 | } | ||
1553 | } | ||
1354 | 1554 | ||
1355 | txring = tx_ring(mac); | 1555 | mactx = dflags | XCT_MACTX_LLEN(skb->len); |
1356 | 1556 | ||
1357 | spin_lock_irqsave(&txring->lock, flags); | 1557 | spin_lock_irqsave(&txring->lock, flags); |
1358 | 1558 | ||
1359 | fill = txring->next_to_fill; | ||
1360 | |||
1361 | /* Avoid stepping on the same cache line that the DMA controller | 1559 | /* Avoid stepping on the same cache line that the DMA controller |
1362 | * is currently about to send, so leave at least 8 words available. | 1560 | * is currently about to send, so leave at least 8 words available. |
1363 | * Total free space needed is mactx + fragments + 8 | 1561 | * Total free space needed is mactx + fragments + 8 |
1364 | */ | 1562 | */ |
1365 | if (RING_AVAIL(txring) < nfrags + 10) { | 1563 | if (RING_AVAIL(txring) < nfrags + 14) { |
1366 | /* no room -- stop the queue and wait for tx intr */ | 1564 | /* no room -- stop the queue and wait for tx intr */ |
1367 | netif_stop_queue(dev); | 1565 | netif_stop_queue(dev); |
1368 | goto out_err; | 1566 | goto out_err; |
1369 | } | 1567 | } |
1370 | 1568 | ||
1569 | /* Queue up checksum + event descriptors, if needed */ | ||
1570 | if (mac->num_cs && skb->ip_summed == CHECKSUM_PARTIAL && skb->len > 1540) { | ||
1571 | csring = mac->cs[mac->last_cs]; | ||
1572 | mac->last_cs = (mac->last_cs + 1) % mac->num_cs; | ||
1573 | |||
1574 | pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring); | ||
1575 | } | ||
1576 | |||
1577 | fill = txring->next_to_fill; | ||
1371 | TX_DESC(txring, fill) = mactx; | 1578 | TX_DESC(txring, fill) = mactx; |
1372 | TX_DESC_INFO(txring, fill).dma = nfrags; | 1579 | TX_DESC_INFO(txring, fill).dma = nfrags; |
1373 | fill++; | 1580 | fill++; |
@@ -1441,12 +1648,33 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget) | |||
1441 | return pkts; | 1648 | return pkts; |
1442 | } | 1649 | } |
1443 | 1650 | ||
1651 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1652 | /* | ||
1653 | * Polling 'interrupt' - used by things like netconsole to send skbs | ||
1654 | * without having to re-enable interrupts. It's not called while | ||
1655 | * the interrupt routine is executing. | ||
1656 | */ | ||
1657 | static void pasemi_mac_netpoll(struct net_device *dev) | ||
1658 | { | ||
1659 | const struct pasemi_mac *mac = netdev_priv(dev); | ||
1660 | |||
1661 | disable_irq(mac->tx->chan.irq); | ||
1662 | pasemi_mac_tx_intr(mac->tx->chan.irq, mac->tx); | ||
1663 | enable_irq(mac->tx->chan.irq); | ||
1664 | |||
1665 | disable_irq(mac->rx->chan.irq); | ||
1666 | pasemi_mac_rx_intr(mac->rx->chan.irq, mac->rx); | ||
1667 | enable_irq(mac->rx->chan.irq); | ||
1668 | } | ||
1669 | #endif | ||
1670 | |||
1444 | static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) | 1671 | static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) |
1445 | { | 1672 | { |
1446 | struct pasemi_mac *mac = netdev_priv(dev); | 1673 | struct pasemi_mac *mac = netdev_priv(dev); |
1447 | unsigned int reg; | 1674 | unsigned int reg; |
1448 | unsigned int rcmdsta; | 1675 | unsigned int rcmdsta = 0; |
1449 | int running; | 1676 | int running; |
1677 | int ret = 0; | ||
1450 | 1678 | ||
1451 | if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU) | 1679 | if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU) |
1452 | return -EINVAL; | 1680 | return -EINVAL; |
@@ -1468,6 +1696,16 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) | |||
1468 | pasemi_mac_pause_rxint(mac); | 1696 | pasemi_mac_pause_rxint(mac); |
1469 | pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE); | 1697 | pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE); |
1470 | pasemi_mac_free_rx_buffers(mac); | 1698 | pasemi_mac_free_rx_buffers(mac); |
1699 | |||
1700 | } | ||
1701 | |||
1702 | /* Setup checksum channels if large MTU and none already allocated */ | ||
1703 | if (new_mtu > 1500 && !mac->num_cs) { | ||
1704 | pasemi_mac_setup_csrings(mac); | ||
1705 | if (!mac->num_cs) { | ||
1706 | ret = -ENOMEM; | ||
1707 | goto out; | ||
1708 | } | ||
1471 | } | 1709 | } |
1472 | 1710 | ||
1473 | /* Change maxf, i.e. what size frames are accepted. | 1711 | /* Change maxf, i.e. what size frames are accepted. |
@@ -1482,6 +1720,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) | |||
1482 | /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ | 1720 | /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ |
1483 | mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; | 1721 | mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; |
1484 | 1722 | ||
1723 | out: | ||
1485 | if (running) { | 1724 | if (running) { |
1486 | write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), | 1725 | write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), |
1487 | rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN); | 1726 | rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN); |
@@ -1494,7 +1733,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) | |||
1494 | pasemi_mac_intf_enable(mac); | 1733 | pasemi_mac_intf_enable(mac); |
1495 | } | 1734 | } |
1496 | 1735 | ||
1497 | return 0; | 1736 | return ret; |
1498 | } | 1737 | } |
1499 | 1738 | ||
1500 | static int __devinit | 1739 | static int __devinit |
@@ -1528,7 +1767,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1528 | netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64); | 1767 | netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64); |
1529 | 1768 | ||
1530 | dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG | | 1769 | dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG | |
1531 | NETIF_F_HIGHDMA; | 1770 | NETIF_F_HIGHDMA | NETIF_F_GSO; |
1532 | 1771 | ||
1533 | mac->lro_mgr.max_aggr = LRO_MAX_AGGR; | 1772 | mac->lro_mgr.max_aggr = LRO_MAX_AGGR; |
1534 | mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; | 1773 | mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; |
@@ -1588,8 +1827,12 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1588 | dev->mtu = PE_DEF_MTU; | 1827 | dev->mtu = PE_DEF_MTU; |
1589 | /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ | 1828 | /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ |
1590 | mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; | 1829 | mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; |
1830 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1831 | dev->poll_controller = pasemi_mac_netpoll; | ||
1832 | #endif | ||
1591 | 1833 | ||
1592 | dev->change_mtu = pasemi_mac_change_mtu; | 1834 | dev->change_mtu = pasemi_mac_change_mtu; |
1835 | dev->ethtool_ops = &pasemi_mac_ethtool_ops; | ||
1593 | 1836 | ||
1594 | if (err) | 1837 | if (err) |
1595 | goto out; | 1838 | goto out; |
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h index 99e7b9329a6f..1a115ec60b53 100644 --- a/drivers/net/pasemi_mac.h +++ b/drivers/net/pasemi_mac.h | |||
@@ -26,7 +26,14 @@ | |||
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/phy.h> | 27 | #include <linux/phy.h> |
28 | 28 | ||
29 | /* Must be a power of two */ | ||
30 | #define RX_RING_SIZE 2048 | ||
31 | #define TX_RING_SIZE 4096 | ||
32 | #define CS_RING_SIZE (TX_RING_SIZE*2) | ||
33 | |||
34 | |||
29 | #define MAX_LRO_DESCRIPTORS 8 | 35 | #define MAX_LRO_DESCRIPTORS 8 |
36 | #define MAX_CS 2 | ||
30 | 37 | ||
31 | struct pasemi_mac_txring { | 38 | struct pasemi_mac_txring { |
32 | struct pasemi_dmachan chan; /* Must be first */ | 39 | struct pasemi_dmachan chan; /* Must be first */ |
@@ -51,6 +58,15 @@ struct pasemi_mac_rxring { | |||
51 | struct pasemi_mac *mac; /* Needed in intr handler */ | 58 | struct pasemi_mac *mac; /* Needed in intr handler */ |
52 | }; | 59 | }; |
53 | 60 | ||
61 | struct pasemi_mac_csring { | ||
62 | struct pasemi_dmachan chan; | ||
63 | unsigned int size; | ||
64 | unsigned int next_to_fill; | ||
65 | int events[2]; | ||
66 | int last_event; | ||
67 | int fun; | ||
68 | }; | ||
69 | |||
54 | struct pasemi_mac { | 70 | struct pasemi_mac { |
55 | struct net_device *netdev; | 71 | struct net_device *netdev; |
56 | struct pci_dev *pdev; | 72 | struct pci_dev *pdev; |
@@ -60,10 +76,12 @@ struct pasemi_mac { | |||
60 | struct napi_struct napi; | 76 | struct napi_struct napi; |
61 | 77 | ||
62 | int bufsz; /* RX ring buffer size */ | 78 | int bufsz; /* RX ring buffer size */ |
79 | int last_cs; | ||
80 | int num_cs; | ||
81 | u32 dma_if; | ||
63 | u8 type; | 82 | u8 type; |
64 | #define MAC_TYPE_GMAC 1 | 83 | #define MAC_TYPE_GMAC 1 |
65 | #define MAC_TYPE_XAUI 2 | 84 | #define MAC_TYPE_XAUI 2 |
66 | u32 dma_if; | ||
67 | 85 | ||
68 | u8 mac_addr[6]; | 86 | u8 mac_addr[6]; |
69 | 87 | ||
@@ -74,6 +92,7 @@ struct pasemi_mac { | |||
74 | 92 | ||
75 | struct pasemi_mac_txring *tx; | 93 | struct pasemi_mac_txring *tx; |
76 | struct pasemi_mac_rxring *rx; | 94 | struct pasemi_mac_rxring *rx; |
95 | struct pasemi_mac_csring *cs[MAX_CS]; | ||
77 | char tx_irq_name[10]; /* "eth%d tx" */ | 96 | char tx_irq_name[10]; /* "eth%d tx" */ |
78 | char rx_irq_name[10]; /* "eth%d rx" */ | 97 | char rx_irq_name[10]; /* "eth%d rx" */ |
79 | int link; | 98 | int link; |
@@ -90,6 +109,16 @@ struct pasemi_mac_buffer { | |||
90 | dma_addr_t dma; | 109 | dma_addr_t dma; |
91 | }; | 110 | }; |
92 | 111 | ||
112 | #define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)]) | ||
113 | #define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)]) | ||
114 | #define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)]) | ||
115 | #define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)]) | ||
116 | #define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)]) | ||
117 | #define CS_DESC(cs, num) ((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)]) | ||
118 | |||
119 | #define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \ | ||
120 | & ((ring)->size - 1)) | ||
121 | #define RING_AVAIL(ring) ((ring->size) - RING_USED(ring)) | ||
93 | 122 | ||
94 | /* PCI register offsets and formats */ | 123 | /* PCI register offsets and formats */ |
95 | 124 | ||
@@ -101,6 +130,7 @@ enum { | |||
101 | PAS_MAC_CFG_ADR0 = 0x8c, | 130 | PAS_MAC_CFG_ADR0 = 0x8c, |
102 | PAS_MAC_CFG_ADR1 = 0x90, | 131 | PAS_MAC_CFG_ADR1 = 0x90, |
103 | PAS_MAC_CFG_TXP = 0x98, | 132 | PAS_MAC_CFG_TXP = 0x98, |
133 | PAS_MAC_CFG_RMON = 0x100, | ||
104 | PAS_MAC_IPC_CHNL = 0x208, | 134 | PAS_MAC_IPC_CHNL = 0x208, |
105 | }; | 135 | }; |
106 | 136 | ||
@@ -172,6 +202,8 @@ enum { | |||
172 | #define PAS_MAC_CFG_TXP_TIFG(x) (((x) << PAS_MAC_CFG_TXP_TIFG_S) & \ | 202 | #define PAS_MAC_CFG_TXP_TIFG(x) (((x) << PAS_MAC_CFG_TXP_TIFG_S) & \ |
173 | PAS_MAC_CFG_TXP_TIFG_M) | 203 | PAS_MAC_CFG_TXP_TIFG_M) |
174 | 204 | ||
205 | #define PAS_MAC_RMON(r) (0x100+(r)*4) | ||
206 | |||
175 | #define PAS_MAC_IPC_CHNL_DCHNO_M 0x003f0000 | 207 | #define PAS_MAC_IPC_CHNL_DCHNO_M 0x003f0000 |
176 | #define PAS_MAC_IPC_CHNL_DCHNO_S 16 | 208 | #define PAS_MAC_IPC_CHNL_DCHNO_S 16 |
177 | #define PAS_MAC_IPC_CHNL_DCHNO(x) (((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \ | 209 | #define PAS_MAC_IPC_CHNL_DCHNO(x) (((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \ |
@@ -181,4 +213,5 @@ enum { | |||
181 | #define PAS_MAC_IPC_CHNL_BCH(x) (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \ | 213 | #define PAS_MAC_IPC_CHNL_BCH(x) (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \ |
182 | PAS_MAC_IPC_CHNL_BCH_M) | 214 | PAS_MAC_IPC_CHNL_BCH_M) |
183 | 215 | ||
216 | |||
184 | #endif /* PASEMI_MAC_H */ | 217 | #endif /* PASEMI_MAC_H */ |
diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c new file mode 100644 index 000000000000..5e8df3afea64 --- /dev/null +++ b/drivers/net/pasemi_mac_ethtool.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006-2008 PA Semi, Inc | ||
3 | * | ||
4 | * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | |||
21 | #include <linux/netdevice.h> | ||
22 | #include <linux/ethtool.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/inet_lro.h> | ||
25 | |||
26 | #include <asm/pasemi_dma.h> | ||
27 | #include "pasemi_mac.h" | ||
28 | |||
29 | static struct { | ||
30 | const char str[ETH_GSTRING_LEN]; | ||
31 | } ethtool_stats_keys[] = { | ||
32 | { "rx-drops" }, | ||
33 | { "rx-bytes" }, | ||
34 | { "rx-packets" }, | ||
35 | { "rx-broadcast-packets" }, | ||
36 | { "rx-multicast-packets" }, | ||
37 | { "rx-crc-errors" }, | ||
38 | { "rx-undersize-errors" }, | ||
39 | { "rx-oversize-errors" }, | ||
40 | { "rx-short-fragment-errors" }, | ||
41 | { "rx-jabber-errors" }, | ||
42 | { "rx-64-byte-packets" }, | ||
43 | { "rx-65-127-byte-packets" }, | ||
44 | { "rx-128-255-byte-packets" }, | ||
45 | { "rx-256-511-byte-packets" }, | ||
46 | { "rx-512-1023-byte-packets" }, | ||
47 | { "rx-1024-1518-byte-packets" }, | ||
48 | { "rx-pause-frames" }, | ||
49 | { "tx-bytes" }, | ||
50 | { "tx-packets" }, | ||
51 | { "tx-broadcast-packets" }, | ||
52 | { "tx-multicast-packets" }, | ||
53 | { "tx-collisions" }, | ||
54 | { "tx-late-collisions" }, | ||
55 | { "tx-excessive-collisions" }, | ||
56 | { "tx-crc-errors" }, | ||
57 | { "tx-undersize-errors" }, | ||
58 | { "tx-oversize-errors" }, | ||
59 | { "tx-64-byte-packets" }, | ||
60 | { "tx-65-127-byte-packets" }, | ||
61 | { "tx-128-255-byte-packets" }, | ||
62 | { "tx-256-511-byte-packets" }, | ||
63 | { "tx-512-1023-byte-packets" }, | ||
64 | { "tx-1024-1518-byte-packets" }, | ||
65 | }; | ||
66 | |||
67 | static int | ||
68 | pasemi_mac_ethtool_get_settings(struct net_device *netdev, | ||
69 | struct ethtool_cmd *cmd) | ||
70 | { | ||
71 | struct pasemi_mac *mac = netdev_priv(netdev); | ||
72 | struct phy_device *phydev = mac->phydev; | ||
73 | |||
74 | return phy_ethtool_gset(phydev, cmd); | ||
75 | } | ||
76 | |||
77 | static void | ||
78 | pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev, | ||
79 | struct ethtool_drvinfo *drvinfo) | ||
80 | { | ||
81 | struct pasemi_mac *mac; | ||
82 | mac = netdev_priv(netdev); | ||
83 | |||
84 | /* clear and fill out info */ | ||
85 | memset(drvinfo, 0, sizeof(struct ethtool_drvinfo)); | ||
86 | strncpy(drvinfo->driver, "pasemi_mac", 12); | ||
87 | strcpy(drvinfo->version, "N/A"); | ||
88 | strcpy(drvinfo->fw_version, "N/A"); | ||
89 | strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32); | ||
90 | } | ||
91 | |||
92 | static u32 | ||
93 | pasemi_mac_ethtool_get_msglevel(struct net_device *netdev) | ||
94 | { | ||
95 | struct pasemi_mac *mac = netdev_priv(netdev); | ||
96 | return mac->msg_enable; | ||
97 | } | ||
98 | |||
99 | static void | ||
100 | pasemi_mac_ethtool_set_msglevel(struct net_device *netdev, | ||
101 | u32 level) | ||
102 | { | ||
103 | struct pasemi_mac *mac = netdev_priv(netdev); | ||
104 | mac->msg_enable = level; | ||
105 | } | ||
106 | |||
107 | |||
108 | static void | ||
109 | pasemi_mac_ethtool_get_ringparam(struct net_device *netdev, | ||
110 | struct ethtool_ringparam *ering) | ||
111 | { | ||
112 | struct pasemi_mac *mac = netdev->priv; | ||
113 | |||
114 | ering->tx_max_pending = TX_RING_SIZE/2; | ||
115 | ering->tx_pending = RING_USED(mac->tx)/2; | ||
116 | ering->rx_max_pending = RX_RING_SIZE/4; | ||
117 | ering->rx_pending = RING_USED(mac->rx)/4; | ||
118 | } | ||
119 | |||
120 | static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset) | ||
121 | { | ||
122 | switch (sset) { | ||
123 | case ETH_SS_STATS: | ||
124 | return ARRAY_SIZE(ethtool_stats_keys); | ||
125 | default: | ||
126 | return -EOPNOTSUPP; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static void pasemi_mac_get_ethtool_stats(struct net_device *netdev, | ||
131 | struct ethtool_stats *stats, u64 *data) | ||
132 | { | ||
133 | struct pasemi_mac *mac = netdev->priv; | ||
134 | int i; | ||
135 | |||
136 | data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if)) | ||
137 | >> PAS_DMA_RXINT_RCMDSTA_DROPS_S; | ||
138 | for (i = 0; i < 32; i++) | ||
139 | data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i)); | ||
140 | } | ||
141 | |||
142 | static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset, | ||
143 | u8 *data) | ||
144 | { | ||
145 | memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys)); | ||
146 | } | ||
147 | |||
148 | const struct ethtool_ops pasemi_mac_ethtool_ops = { | ||
149 | .get_settings = pasemi_mac_ethtool_get_settings, | ||
150 | .get_drvinfo = pasemi_mac_ethtool_get_drvinfo, | ||
151 | .get_msglevel = pasemi_mac_ethtool_get_msglevel, | ||
152 | .set_msglevel = pasemi_mac_ethtool_set_msglevel, | ||
153 | .get_link = ethtool_op_get_link, | ||
154 | .get_ringparam = pasemi_mac_ethtool_get_ringparam, | ||
155 | .get_strings = pasemi_mac_get_strings, | ||
156 | .get_sset_count = pasemi_mac_get_sset_count, | ||
157 | .get_ethtool_stats = pasemi_mac_get_ethtool_stats, | ||
158 | }; | ||
159 | |||
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 7eb6e7e848f4..e365efb3c627 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c | |||
@@ -1266,6 +1266,85 @@ int gelic_net_set_rx_csum(struct net_device *netdev, u32 data) | |||
1266 | return 0; | 1266 | return 0; |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | static void gelic_net_get_wol(struct net_device *netdev, | ||
1270 | struct ethtool_wolinfo *wol) | ||
1271 | { | ||
1272 | if (0 <= ps3_compare_firmware_version(2, 2, 0)) | ||
1273 | wol->supported = WAKE_MAGIC; | ||
1274 | else | ||
1275 | wol->supported = 0; | ||
1276 | |||
1277 | wol->wolopts = ps3_sys_manager_get_wol() ? wol->supported : 0; | ||
1278 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | ||
1279 | } | ||
1280 | static int gelic_net_set_wol(struct net_device *netdev, | ||
1281 | struct ethtool_wolinfo *wol) | ||
1282 | { | ||
1283 | int status; | ||
1284 | struct gelic_card *card; | ||
1285 | u64 v1, v2; | ||
1286 | |||
1287 | if (ps3_compare_firmware_version(2, 2, 0) < 0 || | ||
1288 | !capable(CAP_NET_ADMIN)) | ||
1289 | return -EPERM; | ||
1290 | |||
1291 | if (wol->wolopts & ~WAKE_MAGIC) | ||
1292 | return -EINVAL; | ||
1293 | |||
1294 | card = netdev_card(netdev); | ||
1295 | if (wol->wolopts & WAKE_MAGIC) { | ||
1296 | status = lv1_net_control(bus_id(card), dev_id(card), | ||
1297 | GELIC_LV1_SET_WOL, | ||
1298 | GELIC_LV1_WOL_MAGIC_PACKET, | ||
1299 | 0, GELIC_LV1_WOL_MP_ENABLE, | ||
1300 | &v1, &v2); | ||
1301 | if (status) { | ||
1302 | pr_info("%s: enabling WOL failed %d\n", __func__, | ||
1303 | status); | ||
1304 | status = -EIO; | ||
1305 | goto done; | ||
1306 | } | ||
1307 | status = lv1_net_control(bus_id(card), dev_id(card), | ||
1308 | GELIC_LV1_SET_WOL, | ||
1309 | GELIC_LV1_WOL_ADD_MATCH_ADDR, | ||
1310 | 0, GELIC_LV1_WOL_MATCH_ALL, | ||
1311 | &v1, &v2); | ||
1312 | if (!status) | ||
1313 | ps3_sys_manager_set_wol(1); | ||
1314 | else { | ||
1315 | pr_info("%s: enabling WOL filter failed %d\n", | ||
1316 | __func__, status); | ||
1317 | status = -EIO; | ||
1318 | } | ||
1319 | } else { | ||
1320 | status = lv1_net_control(bus_id(card), dev_id(card), | ||
1321 | GELIC_LV1_SET_WOL, | ||
1322 | GELIC_LV1_WOL_MAGIC_PACKET, | ||
1323 | 0, GELIC_LV1_WOL_MP_DISABLE, | ||
1324 | &v1, &v2); | ||
1325 | if (status) { | ||
1326 | pr_info("%s: disabling WOL failed %d\n", __func__, | ||
1327 | status); | ||
1328 | status = -EIO; | ||
1329 | goto done; | ||
1330 | } | ||
1331 | status = lv1_net_control(bus_id(card), dev_id(card), | ||
1332 | GELIC_LV1_SET_WOL, | ||
1333 | GELIC_LV1_WOL_DELETE_MATCH_ADDR, | ||
1334 | 0, GELIC_LV1_WOL_MATCH_ALL, | ||
1335 | &v1, &v2); | ||
1336 | if (!status) | ||
1337 | ps3_sys_manager_set_wol(0); | ||
1338 | else { | ||
1339 | pr_info("%s: removing WOL filter failed %d\n", | ||
1340 | __func__, status); | ||
1341 | status = -EIO; | ||
1342 | } | ||
1343 | } | ||
1344 | done: | ||
1345 | return status; | ||
1346 | } | ||
1347 | |||
1269 | static struct ethtool_ops gelic_ether_ethtool_ops = { | 1348 | static struct ethtool_ops gelic_ether_ethtool_ops = { |
1270 | .get_drvinfo = gelic_net_get_drvinfo, | 1349 | .get_drvinfo = gelic_net_get_drvinfo, |
1271 | .get_settings = gelic_ether_get_settings, | 1350 | .get_settings = gelic_ether_get_settings, |
@@ -1274,6 +1353,8 @@ static struct ethtool_ops gelic_ether_ethtool_ops = { | |||
1274 | .set_tx_csum = ethtool_op_set_tx_csum, | 1353 | .set_tx_csum = ethtool_op_set_tx_csum, |
1275 | .get_rx_csum = gelic_net_get_rx_csum, | 1354 | .get_rx_csum = gelic_net_get_rx_csum, |
1276 | .set_rx_csum = gelic_net_set_rx_csum, | 1355 | .set_rx_csum = gelic_net_set_rx_csum, |
1356 | .get_wol = gelic_net_get_wol, | ||
1357 | .set_wol = gelic_net_set_wol, | ||
1277 | }; | 1358 | }; |
1278 | 1359 | ||
1279 | /** | 1360 | /** |
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h index 1d39d06797e4..520f143c2c09 100644 --- a/drivers/net/ps3_gelic_net.h +++ b/drivers/net/ps3_gelic_net.h | |||
@@ -182,12 +182,32 @@ enum gelic_lv1_net_control_code { | |||
182 | GELIC_LV1_GET_ETH_PORT_STATUS = 2, | 182 | GELIC_LV1_GET_ETH_PORT_STATUS = 2, |
183 | GELIC_LV1_SET_NEGOTIATION_MODE = 3, | 183 | GELIC_LV1_SET_NEGOTIATION_MODE = 3, |
184 | GELIC_LV1_GET_VLAN_ID = 4, | 184 | GELIC_LV1_GET_VLAN_ID = 4, |
185 | GELIC_LV1_SET_WOL = 5, | ||
185 | GELIC_LV1_GET_CHANNEL = 6, | 186 | GELIC_LV1_GET_CHANNEL = 6, |
186 | GELIC_LV1_POST_WLAN_CMD = 9, | 187 | GELIC_LV1_POST_WLAN_CMD = 9, |
187 | GELIC_LV1_GET_WLAN_CMD_RESULT = 10, | 188 | GELIC_LV1_GET_WLAN_CMD_RESULT = 10, |
188 | GELIC_LV1_GET_WLAN_EVENT = 11 | 189 | GELIC_LV1_GET_WLAN_EVENT = 11 |
189 | }; | 190 | }; |
190 | 191 | ||
192 | /* for GELIC_LV1_SET_WOL */ | ||
193 | enum gelic_lv1_wol_command { | ||
194 | GELIC_LV1_WOL_MAGIC_PACKET = 1, | ||
195 | GELIC_LV1_WOL_ADD_MATCH_ADDR = 6, | ||
196 | GELIC_LV1_WOL_DELETE_MATCH_ADDR = 7, | ||
197 | }; | ||
198 | |||
199 | /* for GELIC_LV1_WOL_MAGIC_PACKET */ | ||
200 | enum gelic_lv1_wol_mp_arg { | ||
201 | GELIC_LV1_WOL_MP_DISABLE = 0, | ||
202 | GELIC_LV1_WOL_MP_ENABLE = 1, | ||
203 | }; | ||
204 | |||
205 | /* for GELIC_LV1_WOL_{ADD,DELETE}_MATCH_ADDR */ | ||
206 | enum gelic_lv1_wol_match_arg { | ||
207 | GELIC_LV1_WOL_MATCH_INDIVIDUAL = 0, | ||
208 | GELIC_LV1_WOL_MATCH_ALL = 1, | ||
209 | }; | ||
210 | |||
191 | /* status returened from GET_ETH_PORT_STATUS */ | 211 | /* status returened from GET_ETH_PORT_STATUS */ |
192 | enum gelic_lv1_ether_port_status { | 212 | enum gelic_lv1_ether_port_status { |
193 | GELIC_LV1_ETHER_LINK_UP = 0x0000000000000001L, | 213 | GELIC_LV1_ETHER_LINK_UP = 0x0000000000000001L, |
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 29a4d650e8a8..2f11254bcc07 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -3853,7 +3853,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
3853 | 3853 | ||
3854 | ugeth_vdbg("%s: IN", __FUNCTION__); | 3854 | ugeth_vdbg("%s: IN", __FUNCTION__); |
3855 | 3855 | ||
3856 | prop = of_get_property(np, "device-id", NULL); | 3856 | prop = of_get_property(np, "cell-index", NULL); |
3857 | if (!prop) { | ||
3858 | prop = of_get_property(np, "device-id", NULL); | ||
3859 | if (!prop) | ||
3860 | return -ENODEV; | ||
3861 | } | ||
3862 | |||
3857 | ucc_num = *prop - 1; | 3863 | ucc_num = *prop - 1; |
3858 | if ((ucc_num < 0) || (ucc_num > 7)) | 3864 | if ((ucc_num < 0) || (ucc_num > 7)) |
3859 | return -ENODEV; | 3865 | return -ENODEV; |
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c index e4d3f330bac3..2af490781005 100644 --- a/drivers/net/ucc_geth_mii.c +++ b/drivers/net/ucc_geth_mii.c | |||
@@ -203,9 +203,14 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma | |||
203 | if ((res.start >= tempres.start) && | 203 | if ((res.start >= tempres.start) && |
204 | (res.end <= tempres.end)) { | 204 | (res.end <= tempres.end)) { |
205 | /* set this UCC to be the MII master */ | 205 | /* set this UCC to be the MII master */ |
206 | const u32 *id = of_get_property(tempnp, "device-id", NULL); | 206 | const u32 *id; |
207 | if (id == NULL) | 207 | |
208 | goto bus_register_fail; | 208 | id = of_get_property(tempnp, "cell-index", NULL); |
209 | if (!id) { | ||
210 | id = of_get_property(tempnp, "device-id", NULL); | ||
211 | if (!id) | ||
212 | goto bus_register_fail; | ||
213 | } | ||
209 | 214 | ||
210 | ucc_set_qe_mux_mii_mng(*id - 1); | 215 | ucc_set_qe_mux_mii_mng(*id - 1); |
211 | 216 | ||
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index c03072b12f42..3a7a11a75fb4 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -1,3 +1,15 @@ | |||
1 | config OF_DEVICE | 1 | config OF_DEVICE |
2 | def_bool y | 2 | def_bool y |
3 | depends on OF && (SPARC || PPC_OF) | 3 | depends on OF && (SPARC || PPC_OF) |
4 | |||
5 | config OF_GPIO | ||
6 | def_bool y | ||
7 | depends on OF && PPC_OF && HAVE_GPIO_LIB | ||
8 | help | ||
9 | OpenFirmware GPIO accessors | ||
10 | |||
11 | config OF_I2C | ||
12 | def_tristate I2C | ||
13 | depends on PPC_OF && I2C | ||
14 | help | ||
15 | OpenFirmware I2C accessors | ||
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index ab9be5d5255b..548772e871fd 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -1,2 +1,4 @@ | |||
1 | obj-y = base.o | 1 | obj-y = base.o |
2 | obj-$(CONFIG_OF_DEVICE) += device.o platform.o | 2 | obj-$(CONFIG_OF_DEVICE) += device.o platform.o |
3 | obj-$(CONFIG_OF_GPIO) += gpio.o | ||
4 | obj-$(CONFIG_OF_I2C) += of_i2c.o | ||
diff --git a/drivers/of/base.c b/drivers/of/base.c index 80c9deca5f35..9bd7c4a31253 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -117,6 +117,32 @@ int of_device_is_compatible(const struct device_node *device, | |||
117 | EXPORT_SYMBOL(of_device_is_compatible); | 117 | EXPORT_SYMBOL(of_device_is_compatible); |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * of_device_is_available - check if a device is available for use | ||
121 | * | ||
122 | * @device: Node to check for availability | ||
123 | * | ||
124 | * Returns 1 if the status property is absent or set to "okay" or "ok", | ||
125 | * 0 otherwise | ||
126 | */ | ||
127 | int of_device_is_available(const struct device_node *device) | ||
128 | { | ||
129 | const char *status; | ||
130 | int statlen; | ||
131 | |||
132 | status = of_get_property(device, "status", &statlen); | ||
133 | if (status == NULL) | ||
134 | return 1; | ||
135 | |||
136 | if (statlen > 0) { | ||
137 | if (!strcmp(status, "okay") || !strcmp(status, "ok")) | ||
138 | return 1; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | EXPORT_SYMBOL(of_device_is_available); | ||
144 | |||
145 | /** | ||
120 | * of_get_parent - Get a node's parent if any | 146 | * of_get_parent - Get a node's parent if any |
121 | * @node: Node to get parent | 147 | * @node: Node to get parent |
122 | * | 148 | * |
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c new file mode 100644 index 000000000000..000681e98f2c --- /dev/null +++ b/drivers/of/gpio.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * OF helpers for the GPIO API | ||
3 | * | ||
4 | * Copyright (c) 2007-2008 MontaVista Software, Inc. | ||
5 | * | ||
6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_gpio.h> | ||
19 | #include <asm/prom.h> | ||
20 | |||
21 | /** | ||
22 | * of_get_gpio - Get a GPIO number from the device tree to use with GPIO API | ||
23 | * @np: device node to get GPIO from | ||
24 | * @index: index of the GPIO | ||
25 | * | ||
26 | * Returns GPIO number to use with Linux generic GPIO API, or one of the errno | ||
27 | * value on the error condition. | ||
28 | */ | ||
29 | int of_get_gpio(struct device_node *np, int index) | ||
30 | { | ||
31 | int ret = -EINVAL; | ||
32 | struct device_node *gc; | ||
33 | struct of_gpio_chip *of_gc = NULL; | ||
34 | int size; | ||
35 | const u32 *gpios; | ||
36 | u32 nr_cells; | ||
37 | int i; | ||
38 | const void *gpio_spec; | ||
39 | const u32 *gpio_cells; | ||
40 | int gpio_index = 0; | ||
41 | |||
42 | gpios = of_get_property(np, "gpios", &size); | ||
43 | if (!gpios) { | ||
44 | ret = -ENOENT; | ||
45 | goto err0; | ||
46 | } | ||
47 | nr_cells = size / sizeof(u32); | ||
48 | |||
49 | for (i = 0; i < nr_cells; gpio_index++) { | ||
50 | const phandle *gpio_phandle; | ||
51 | |||
52 | gpio_phandle = gpios + i; | ||
53 | gpio_spec = gpio_phandle + 1; | ||
54 | |||
55 | /* one cell hole in the gpios = <>; */ | ||
56 | if (!*gpio_phandle) { | ||
57 | if (gpio_index == index) | ||
58 | return -ENOENT; | ||
59 | i++; | ||
60 | continue; | ||
61 | } | ||
62 | |||
63 | gc = of_find_node_by_phandle(*gpio_phandle); | ||
64 | if (!gc) { | ||
65 | pr_debug("%s: could not find phandle for gpios\n", | ||
66 | np->full_name); | ||
67 | goto err0; | ||
68 | } | ||
69 | |||
70 | of_gc = gc->data; | ||
71 | if (!of_gc) { | ||
72 | pr_debug("%s: gpio controller %s isn't registered\n", | ||
73 | np->full_name, gc->full_name); | ||
74 | goto err1; | ||
75 | } | ||
76 | |||
77 | gpio_cells = of_get_property(gc, "#gpio-cells", &size); | ||
78 | if (!gpio_cells || size != sizeof(*gpio_cells) || | ||
79 | *gpio_cells != of_gc->gpio_cells) { | ||
80 | pr_debug("%s: wrong #gpio-cells for %s\n", | ||
81 | np->full_name, gc->full_name); | ||
82 | goto err1; | ||
83 | } | ||
84 | |||
85 | /* Next phandle is at phandle cells + #gpio-cells */ | ||
86 | i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells; | ||
87 | if (i >= nr_cells + 1) { | ||
88 | pr_debug("%s: insufficient gpio-spec length\n", | ||
89 | np->full_name); | ||
90 | goto err1; | ||
91 | } | ||
92 | |||
93 | if (gpio_index == index) | ||
94 | break; | ||
95 | |||
96 | of_gc = NULL; | ||
97 | of_node_put(gc); | ||
98 | } | ||
99 | |||
100 | if (!of_gc) { | ||
101 | ret = -ENOENT; | ||
102 | goto err0; | ||
103 | } | ||
104 | |||
105 | ret = of_gc->xlate(of_gc, np, gpio_spec); | ||
106 | if (ret < 0) | ||
107 | goto err1; | ||
108 | |||
109 | ret += of_gc->gc.base; | ||
110 | err1: | ||
111 | of_node_put(gc); | ||
112 | err0: | ||
113 | pr_debug("%s exited with status %d\n", __func__, ret); | ||
114 | return ret; | ||
115 | } | ||
116 | EXPORT_SYMBOL(of_get_gpio); | ||
117 | |||
118 | /** | ||
119 | * of_gpio_simple_xlate - translate gpio_spec to the GPIO number | ||
120 | * @of_gc: pointer to the of_gpio_chip structure | ||
121 | * @np: device node of the GPIO chip | ||
122 | * @gpio_spec: gpio specifier as found in the device tree | ||
123 | * | ||
124 | * This is simple translation function, suitable for the most 1:1 mapped | ||
125 | * gpio chips. This function performs only one sanity check: whether gpio | ||
126 | * is less than ngpios (that is specified in the gpio_chip). | ||
127 | */ | ||
128 | int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np, | ||
129 | const void *gpio_spec) | ||
130 | { | ||
131 | const u32 *gpio = gpio_spec; | ||
132 | |||
133 | if (*gpio > of_gc->gc.ngpio) | ||
134 | return -EINVAL; | ||
135 | |||
136 | return *gpio; | ||
137 | } | ||
138 | EXPORT_SYMBOL(of_gpio_simple_xlate); | ||
139 | |||
140 | /* Should be sufficient for now, later we'll use dynamic bases. */ | ||
141 | #if defined(CONFIG_PPC32) || defined(CONFIG_SPARC32) | ||
142 | #define GPIOS_PER_CHIP 32 | ||
143 | #else | ||
144 | #define GPIOS_PER_CHIP 64 | ||
145 | #endif | ||
146 | |||
147 | static int of_get_gpiochip_base(struct device_node *np) | ||
148 | { | ||
149 | struct device_node *gc = NULL; | ||
150 | int gpiochip_base = 0; | ||
151 | |||
152 | while ((gc = of_find_all_nodes(gc))) { | ||
153 | if (!of_get_property(gc, "gpio-controller", NULL)) | ||
154 | continue; | ||
155 | |||
156 | if (gc != np) { | ||
157 | gpiochip_base += GPIOS_PER_CHIP; | ||
158 | continue; | ||
159 | } | ||
160 | |||
161 | of_node_put(gc); | ||
162 | |||
163 | if (gpiochip_base >= ARCH_NR_GPIOS) | ||
164 | return -ENOSPC; | ||
165 | |||
166 | return gpiochip_base; | ||
167 | } | ||
168 | |||
169 | return -ENOENT; | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank) | ||
174 | * @np: device node of the GPIO chip | ||
175 | * @mm_gc: pointer to the of_mm_gpio_chip allocated structure | ||
176 | * | ||
177 | * To use this function you should allocate and fill mm_gc with: | ||
178 | * | ||
179 | * 1) In the gpio_chip structure: | ||
180 | * - all the callbacks | ||
181 | * | ||
182 | * 2) In the of_gpio_chip structure: | ||
183 | * - gpio_cells | ||
184 | * - xlate callback (optional) | ||
185 | * | ||
186 | * 3) In the of_mm_gpio_chip structure: | ||
187 | * - save_regs callback (optional) | ||
188 | * | ||
189 | * If succeeded, this function will map bank's memory and will | ||
190 | * do all necessary work for you. Then you'll able to use .regs | ||
191 | * to manage GPIOs from the callbacks. | ||
192 | */ | ||
193 | int of_mm_gpiochip_add(struct device_node *np, | ||
194 | struct of_mm_gpio_chip *mm_gc) | ||
195 | { | ||
196 | int ret = -ENOMEM; | ||
197 | struct of_gpio_chip *of_gc = &mm_gc->of_gc; | ||
198 | struct gpio_chip *gc = &of_gc->gc; | ||
199 | |||
200 | gc->label = kstrdup(np->full_name, GFP_KERNEL); | ||
201 | if (!gc->label) | ||
202 | goto err0; | ||
203 | |||
204 | mm_gc->regs = of_iomap(np, 0); | ||
205 | if (!mm_gc->regs) | ||
206 | goto err1; | ||
207 | |||
208 | gc->base = of_get_gpiochip_base(np); | ||
209 | if (gc->base < 0) { | ||
210 | ret = gc->base; | ||
211 | goto err1; | ||
212 | } | ||
213 | |||
214 | if (!of_gc->xlate) | ||
215 | of_gc->xlate = of_gpio_simple_xlate; | ||
216 | |||
217 | if (mm_gc->save_regs) | ||
218 | mm_gc->save_regs(mm_gc); | ||
219 | |||
220 | np->data = of_gc; | ||
221 | |||
222 | ret = gpiochip_add(gc); | ||
223 | if (ret) | ||
224 | goto err2; | ||
225 | |||
226 | /* We don't want to lose the node and its ->data */ | ||
227 | of_node_get(np); | ||
228 | |||
229 | pr_debug("%s: registered as generic GPIO chip, base is %d\n", | ||
230 | np->full_name, gc->base); | ||
231 | return 0; | ||
232 | err2: | ||
233 | np->data = NULL; | ||
234 | iounmap(mm_gc->regs); | ||
235 | err1: | ||
236 | kfree(gc->label); | ||
237 | err0: | ||
238 | pr_err("%s: GPIO chip registration failed with status %d\n", | ||
239 | np->full_name, ret); | ||
240 | return ret; | ||
241 | } | ||
242 | EXPORT_SYMBOL(of_mm_gpiochip_add); | ||
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c new file mode 100644 index 000000000000..631689171159 --- /dev/null +++ b/drivers/of/of_i2c.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * OF helpers for the I2C API | ||
3 | * | ||
4 | * Copyright (c) 2008 Jochen Friedrich <jochen@scram.de> | ||
5 | * | ||
6 | * Based on a previous patch from Jon Smirl <jonsmirl@gmail.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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/of.h> | ||
16 | |||
17 | struct i2c_driver_device { | ||
18 | char *of_device; | ||
19 | char *i2c_type; | ||
20 | }; | ||
21 | |||
22 | static struct i2c_driver_device i2c_devices[] = { | ||
23 | { "dallas,ds1374", "rtc-ds1374" }, | ||
24 | }; | ||
25 | |||
26 | static int of_find_i2c_driver(struct device_node *node, | ||
27 | struct i2c_board_info *info) | ||
28 | { | ||
29 | int i, cplen; | ||
30 | const char *compatible; | ||
31 | const char *p; | ||
32 | |||
33 | /* 1. search for exception list entry */ | ||
34 | for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) { | ||
35 | if (!of_device_is_compatible(node, i2c_devices[i].of_device)) | ||
36 | continue; | ||
37 | if (strlcpy(info->type, i2c_devices[i].i2c_type, | ||
38 | I2C_NAME_SIZE) >= I2C_NAME_SIZE) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | compatible = of_get_property(node, "compatible", &cplen); | ||
45 | if (!compatible) | ||
46 | return -ENODEV; | ||
47 | |||
48 | /* 2. search for linux,<i2c-type> entry */ | ||
49 | p = compatible; | ||
50 | while (cplen > 0) { | ||
51 | if (!strncmp(p, "linux,", 6)) { | ||
52 | p += 6; | ||
53 | if (strlcpy(info->type, p, | ||
54 | I2C_NAME_SIZE) >= I2C_NAME_SIZE) | ||
55 | return -ENOMEM; | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | i = strlen(p) + 1; | ||
60 | p += i; | ||
61 | cplen -= i; | ||
62 | } | ||
63 | |||
64 | /* 3. take fist compatible entry and strip manufacturer */ | ||
65 | p = strchr(compatible, ','); | ||
66 | if (!p) | ||
67 | return -ENODEV; | ||
68 | p++; | ||
69 | if (strlcpy(info->type, p, I2C_NAME_SIZE) >= I2C_NAME_SIZE) | ||
70 | return -ENOMEM; | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | void of_register_i2c_devices(struct i2c_adapter *adap, | ||
75 | struct device_node *adap_node) | ||
76 | { | ||
77 | void *result; | ||
78 | struct device_node *node; | ||
79 | |||
80 | for_each_child_of_node(adap_node, node) { | ||
81 | struct i2c_board_info info = {}; | ||
82 | const u32 *addr; | ||
83 | int len; | ||
84 | |||
85 | addr = of_get_property(node, "reg", &len); | ||
86 | if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) { | ||
87 | printk(KERN_ERR | ||
88 | "of-i2c: invalid i2c device entry\n"); | ||
89 | continue; | ||
90 | } | ||
91 | |||
92 | info.irq = irq_of_parse_and_map(node, 0); | ||
93 | if (info.irq == NO_IRQ) | ||
94 | info.irq = -1; | ||
95 | |||
96 | if (of_find_i2c_driver(node, &info) < 0) { | ||
97 | irq_dispose_mapping(info.irq); | ||
98 | continue; | ||
99 | } | ||
100 | |||
101 | info.addr = *addr; | ||
102 | |||
103 | request_module(info.type); | ||
104 | |||
105 | result = i2c_new_device(adap, &info); | ||
106 | if (result == NULL) { | ||
107 | printk(KERN_ERR | ||
108 | "of-i2c: Failed to load driver for %s\n", | ||
109 | info.type); | ||
110 | irq_dispose_mapping(info.irq); | ||
111 | continue; | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | EXPORT_SYMBOL(of_register_i2c_devices); | ||
diff --git a/drivers/ps3/ps3-sys-manager.c b/drivers/ps3/ps3-sys-manager.c index d4f6f960dd18..7605453b74fd 100644 --- a/drivers/ps3/ps3-sys-manager.c +++ b/drivers/ps3/ps3-sys-manager.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/reboot.h> | 24 | #include <linux/reboot.h> |
25 | 25 | ||
26 | #include <asm/firmware.h> | 26 | #include <asm/firmware.h> |
27 | #include <asm/lv1call.h> | ||
27 | #include <asm/ps3.h> | 28 | #include <asm/ps3.h> |
28 | 29 | ||
29 | #include "vuart.h" | 30 | #include "vuart.h" |
@@ -187,6 +188,7 @@ enum ps3_sys_manager_next_op { | |||
187 | * controller, and bluetooth controller. | 188 | * controller, and bluetooth controller. |
188 | * @PS3_SM_WAKE_RTC: | 189 | * @PS3_SM_WAKE_RTC: |
189 | * @PS3_SM_WAKE_RTC_ERROR: | 190 | * @PS3_SM_WAKE_RTC_ERROR: |
191 | * @PS3_SM_WAKE_W_O_L: Ether or wireless LAN. | ||
190 | * @PS3_SM_WAKE_P_O_R: Power on reset. | 192 | * @PS3_SM_WAKE_P_O_R: Power on reset. |
191 | * | 193 | * |
192 | * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN. | 194 | * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN. |
@@ -200,10 +202,19 @@ enum ps3_sys_manager_wake_source { | |||
200 | PS3_SM_WAKE_DEFAULT = 0, | 202 | PS3_SM_WAKE_DEFAULT = 0, |
201 | PS3_SM_WAKE_RTC = 0x00000040, | 203 | PS3_SM_WAKE_RTC = 0x00000040, |
202 | PS3_SM_WAKE_RTC_ERROR = 0x00000080, | 204 | PS3_SM_WAKE_RTC_ERROR = 0x00000080, |
205 | PS3_SM_WAKE_W_O_L = 0x00000400, | ||
203 | PS3_SM_WAKE_P_O_R = 0x80000000, | 206 | PS3_SM_WAKE_P_O_R = 0x80000000, |
204 | }; | 207 | }; |
205 | 208 | ||
206 | /** | 209 | /** |
210 | * user_wake_sources - User specified wakeup sources. | ||
211 | * | ||
212 | * Logical OR of enum ps3_sys_manager_wake_source types. | ||
213 | */ | ||
214 | |||
215 | static u32 user_wake_sources = PS3_SM_WAKE_DEFAULT; | ||
216 | |||
217 | /** | ||
207 | * enum ps3_sys_manager_cmd - Command from system manager to guest. | 218 | * enum ps3_sys_manager_cmd - Command from system manager to guest. |
208 | * | 219 | * |
209 | * The guest completes the actions needed, then acks or naks the command via | 220 | * The guest completes the actions needed, then acks or naks the command via |
@@ -581,6 +592,23 @@ fail_id: | |||
581 | return -EIO; | 592 | return -EIO; |
582 | } | 593 | } |
583 | 594 | ||
595 | static void ps3_sys_manager_fin(struct ps3_system_bus_device *dev) | ||
596 | { | ||
597 | ps3_sys_manager_send_request_shutdown(dev); | ||
598 | |||
599 | pr_emerg("System Halted, OK to turn off power\n"); | ||
600 | |||
601 | while (ps3_sys_manager_handle_msg(dev)) { | ||
602 | /* pause until next DEC interrupt */ | ||
603 | lv1_pause(0); | ||
604 | } | ||
605 | |||
606 | while (1) { | ||
607 | /* pause, ignoring DEC interrupt */ | ||
608 | lv1_pause(1); | ||
609 | } | ||
610 | } | ||
611 | |||
584 | /** | 612 | /** |
585 | * ps3_sys_manager_final_power_off - The final platform machine_power_off routine. | 613 | * ps3_sys_manager_final_power_off - The final platform machine_power_off routine. |
586 | * | 614 | * |
@@ -601,13 +629,9 @@ static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev) | |||
601 | ps3_vuart_cancel_async(dev); | 629 | ps3_vuart_cancel_async(dev); |
602 | 630 | ||
603 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, | 631 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, |
604 | PS3_SM_WAKE_DEFAULT); | 632 | user_wake_sources); |
605 | ps3_sys_manager_send_request_shutdown(dev); | ||
606 | |||
607 | pr_emerg("System Halted, OK to turn off power\n"); | ||
608 | 633 | ||
609 | while (1) | 634 | ps3_sys_manager_fin(dev); |
610 | ps3_sys_manager_handle_msg(dev); | ||
611 | } | 635 | } |
612 | 636 | ||
613 | /** | 637 | /** |
@@ -638,14 +662,42 @@ static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev) | |||
638 | 662 | ||
639 | ps3_sys_manager_send_attr(dev, 0); | 663 | ps3_sys_manager_send_attr(dev, 0); |
640 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT, | 664 | ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT, |
641 | PS3_SM_WAKE_DEFAULT); | 665 | user_wake_sources); |
642 | ps3_sys_manager_send_request_shutdown(dev); | ||
643 | 666 | ||
644 | pr_emerg("System Halted, OK to turn off power\n"); | 667 | ps3_sys_manager_fin(dev); |
668 | } | ||
669 | |||
670 | /** | ||
671 | * ps3_sys_manager_get_wol - Get wake-on-lan setting. | ||
672 | */ | ||
673 | |||
674 | int ps3_sys_manager_get_wol(void) | ||
675 | { | ||
676 | pr_debug("%s:%d\n", __func__, __LINE__); | ||
677 | |||
678 | return (user_wake_sources & PS3_SM_WAKE_W_O_L) != 0; | ||
679 | } | ||
680 | EXPORT_SYMBOL_GPL(ps3_sys_manager_get_wol); | ||
681 | |||
682 | /** | ||
683 | * ps3_sys_manager_set_wol - Set wake-on-lan setting. | ||
684 | */ | ||
685 | |||
686 | void ps3_sys_manager_set_wol(int state) | ||
687 | { | ||
688 | static DEFINE_MUTEX(mutex); | ||
689 | |||
690 | mutex_lock(&mutex); | ||
691 | |||
692 | pr_debug("%s:%d: %d\n", __func__, __LINE__, state); | ||
645 | 693 | ||
646 | while (1) | 694 | if (state) |
647 | ps3_sys_manager_handle_msg(dev); | 695 | user_wake_sources |= PS3_SM_WAKE_W_O_L; |
696 | else | ||
697 | user_wake_sources &= ~PS3_SM_WAKE_W_O_L; | ||
698 | mutex_unlock(&mutex); | ||
648 | } | 699 | } |
700 | EXPORT_SYMBOL_GPL(ps3_sys_manager_set_wol); | ||
649 | 701 | ||
650 | /** | 702 | /** |
651 | * ps3_sys_manager_work - Asynchronous read handler. | 703 | * ps3_sys_manager_work - Asynchronous read handler. |
diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c index 31648f7d9ae1..474225852b63 100644 --- a/drivers/ps3/sys-manager-core.c +++ b/drivers/ps3/sys-manager-core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <asm/lv1call.h> | ||
22 | #include <asm/ps3.h> | 23 | #include <asm/ps3.h> |
23 | 24 | ||
24 | /** | 25 | /** |
@@ -50,10 +51,7 @@ void ps3_sys_manager_power_off(void) | |||
50 | if (ps3_sys_manager_ops.power_off) | 51 | if (ps3_sys_manager_ops.power_off) |
51 | ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev); | 52 | ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev); |
52 | 53 | ||
53 | printk(KERN_EMERG "System Halted, OK to turn off power\n"); | 54 | ps3_sys_manager_halt(); |
54 | local_irq_disable(); | ||
55 | while (1) | ||
56 | (void)0; | ||
57 | } | 55 | } |
58 | 56 | ||
59 | void ps3_sys_manager_restart(void) | 57 | void ps3_sys_manager_restart(void) |
@@ -61,8 +59,14 @@ void ps3_sys_manager_restart(void) | |||
61 | if (ps3_sys_manager_ops.restart) | 59 | if (ps3_sys_manager_ops.restart) |
62 | ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev); | 60 | ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev); |
63 | 61 | ||
64 | printk(KERN_EMERG "System Halted, OK to turn off power\n"); | 62 | ps3_sys_manager_halt(); |
63 | } | ||
64 | |||
65 | void ps3_sys_manager_halt(void) | ||
66 | { | ||
67 | pr_emerg("System Halted, OK to turn off power\n"); | ||
65 | local_irq_disable(); | 68 | local_irq_disable(); |
66 | while (1) | 69 | while (1) |
67 | (void)0; | 70 | lv1_pause(1); |
68 | } | 71 | } |
72 | |||
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 32b9737759c4..0cc39f82d7c5 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h | |||
@@ -92,6 +92,9 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR]; | |||
92 | 92 | ||
93 | /* these are located in their respective files */ | 93 | /* these are located in their respective files */ |
94 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd); | 94 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd); |
95 | void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | ||
96 | struct device_node *np); | ||
97 | void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram); | ||
95 | int cpm_uart_init_portdesc(void); | 98 | int cpm_uart_init_portdesc(void); |
96 | int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); | 99 | int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); |
97 | void cpm_uart_freebuf(struct uart_cpm_port *pinfo); | 100 | void cpm_uart_freebuf(struct uart_cpm_port *pinfo); |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 236af9d33851..a638ba0679ac 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -966,24 +966,23 @@ static int cpm_uart_init_port(struct device_node *np, | |||
966 | if (!mem) | 966 | if (!mem) |
967 | return -ENOMEM; | 967 | return -ENOMEM; |
968 | 968 | ||
969 | pram = of_iomap(np, 1); | ||
970 | if (!pram) { | ||
971 | ret = -ENOMEM; | ||
972 | goto out_mem; | ||
973 | } | ||
974 | |||
975 | if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") || | 969 | if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") || |
976 | of_device_is_compatible(np, "fsl,cpm2-scc-uart")) { | 970 | of_device_is_compatible(np, "fsl,cpm2-scc-uart")) { |
977 | pinfo->sccp = mem; | 971 | pinfo->sccp = mem; |
978 | pinfo->sccup = pram; | 972 | pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np); |
979 | } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") || | 973 | } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") || |
980 | of_device_is_compatible(np, "fsl,cpm2-smc-uart")) { | 974 | of_device_is_compatible(np, "fsl,cpm2-smc-uart")) { |
981 | pinfo->flags |= FLAG_SMC; | 975 | pinfo->flags |= FLAG_SMC; |
982 | pinfo->smcp = mem; | 976 | pinfo->smcp = mem; |
983 | pinfo->smcup = pram; | 977 | pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np); |
984 | } else { | 978 | } else { |
985 | ret = -ENODEV; | 979 | ret = -ENODEV; |
986 | goto out_pram; | 980 | goto out_mem; |
981 | } | ||
982 | |||
983 | if (!pram) { | ||
984 | ret = -ENOMEM; | ||
985 | goto out_mem; | ||
987 | } | 986 | } |
988 | 987 | ||
989 | pinfo->tx_nrfifos = TX_NUM_FIFO; | 988 | pinfo->tx_nrfifos = TX_NUM_FIFO; |
@@ -1007,7 +1006,7 @@ static int cpm_uart_init_port(struct device_node *np, | |||
1007 | return cpm_uart_request_port(&pinfo->port); | 1006 | return cpm_uart_request_port(&pinfo->port); |
1008 | 1007 | ||
1009 | out_pram: | 1008 | out_pram: |
1010 | iounmap(pram); | 1009 | cpm_uart_unmap_pram(pinfo, pram); |
1011 | out_mem: | 1010 | out_mem: |
1012 | iounmap(mem); | 1011 | iounmap(mem); |
1013 | return ret; | 1012 | return ret; |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 6ea0366e26ae..74f1432bb248 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -45,6 +45,8 @@ | |||
45 | #include <linux/serial_core.h> | 45 | #include <linux/serial_core.h> |
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | 47 | ||
48 | #include <linux/of.h> | ||
49 | |||
48 | #include "cpm_uart.h" | 50 | #include "cpm_uart.h" |
49 | 51 | ||
50 | /**************************************************************/ | 52 | /**************************************************************/ |
@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | |||
54 | { | 56 | { |
55 | cpm_command(port->command, cmd); | 57 | cpm_command(port->command, cmd); |
56 | } | 58 | } |
59 | |||
60 | void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | ||
61 | struct device_node *np) | ||
62 | { | ||
63 | return of_iomap(np, 1); | ||
64 | } | ||
65 | |||
66 | void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) | ||
67 | { | ||
68 | iounmap(pram); | ||
69 | } | ||
70 | |||
57 | #else | 71 | #else |
58 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | 72 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) |
59 | { | 73 | { |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index d9af06a791ba..bb862e2f54cf 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -41,6 +41,9 @@ | |||
41 | #include <asm/io.h> | 41 | #include <asm/io.h> |
42 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
43 | #include <asm/fs_pd.h> | 43 | #include <asm/fs_pd.h> |
44 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
45 | #include <asm/prom.h> | ||
46 | #endif | ||
44 | 47 | ||
45 | #include <linux/serial_core.h> | 48 | #include <linux/serial_core.h> |
46 | #include <linux/kernel.h> | 49 | #include <linux/kernel.h> |
@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | |||
54 | { | 57 | { |
55 | cpm_command(port->command, cmd); | 58 | cpm_command(port->command, cmd); |
56 | } | 59 | } |
60 | |||
61 | void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | ||
62 | struct device_node *np) | ||
63 | { | ||
64 | void __iomem *pram; | ||
65 | unsigned long offset; | ||
66 | struct resource res; | ||
67 | unsigned long len; | ||
68 | |||
69 | /* Don't remap parameter RAM if it has already been initialized | ||
70 | * during console setup. | ||
71 | */ | ||
72 | if (IS_SMC(port) && port->smcup) | ||
73 | return port->smcup; | ||
74 | else if (!IS_SMC(port) && port->sccup) | ||
75 | return port->sccup; | ||
76 | |||
77 | if (of_address_to_resource(np, 1, &res)) | ||
78 | return NULL; | ||
79 | |||
80 | len = 1 + res.end - res.start; | ||
81 | pram = ioremap(res.start, len); | ||
82 | if (!pram) | ||
83 | return NULL; | ||
84 | |||
85 | if (!IS_SMC(port)) | ||
86 | return pram; | ||
87 | |||
88 | if (len != 2) { | ||
89 | printk(KERN_WARNING "cpm_uart[%d]: device tree references " | ||
90 | "SMC pram, using boot loader/wrapper pram mapping. " | ||
91 | "Please fix your device tree to reference the pram " | ||
92 | "base register instead.\n", | ||
93 | port->port.line); | ||
94 | return pram; | ||
95 | } | ||
96 | |||
97 | offset = cpm_dpalloc(PROFF_SMC_SIZE, 64); | ||
98 | out_be16(pram, offset); | ||
99 | iounmap(pram); | ||
100 | return cpm_muram_addr(offset); | ||
101 | } | ||
102 | |||
103 | void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) | ||
104 | { | ||
105 | if (!IS_SMC(port)) | ||
106 | iounmap(pram); | ||
107 | } | ||
108 | |||
57 | #else | 109 | #else |
58 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | 110 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) |
59 | { | 111 | { |
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index c0e50a461055..8aacfb78deab 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c | |||
@@ -56,7 +56,9 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, | |||
56 | port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | 56 | port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
57 | | UPF_FIXED_PORT; | 57 | | UPF_FIXED_PORT; |
58 | port->dev = &ofdev->dev; | 58 | port->dev = &ofdev->dev; |
59 | port->custom_divisor = *clk / (16 * (*spd)); | 59 | /* If current-speed was set, then try not to change it. */ |
60 | if (spd) | ||
61 | port->custom_divisor = *clk / (16 * (*spd)); | ||
60 | 62 | ||
61 | return 0; | 63 | return 0; |
62 | } | 64 | } |
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index e0994f061001..5e4310ccd591 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c | |||
@@ -1270,10 +1270,18 @@ static int ucc_uart_probe(struct of_device *ofdev, | |||
1270 | 1270 | ||
1271 | /* Get the UCC number (device ID) */ | 1271 | /* Get the UCC number (device ID) */ |
1272 | /* UCCs are numbered 1-7 */ | 1272 | /* UCCs are numbered 1-7 */ |
1273 | iprop = of_get_property(np, "device-id", NULL); | 1273 | iprop = of_get_property(np, "cell-index", NULL); |
1274 | if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) { | 1274 | if (!iprop) { |
1275 | dev_err(&ofdev->dev, | 1275 | iprop = of_get_property(np, "device-id", NULL); |
1276 | "missing or invalid UCC specified in device tree\n"); | 1276 | if (!iprop) { |
1277 | dev_err(&ofdev->dev, "UCC is unspecified in " | ||
1278 | "device tree\n"); | ||
1279 | return -EINVAL; | ||
1280 | } | ||
1281 | } | ||
1282 | |||
1283 | if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) { | ||
1284 | dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop); | ||
1277 | kfree(qe_port); | 1285 | kfree(qe_port); |
1278 | return -ENODEV; | 1286 | return -ENODEV; |
1279 | } | 1287 | } |