diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 13:59:31 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 13:59:31 -0400 |
| commit | 72e58063d63c5f0a7bf65312f1e3a5ed9bb5c2ff (patch) | |
| tree | df5c21244d46aacef47e6b7fff3ad02c3612b15c | |
| parent | 57c155d51e2f3d7411eeac5e7fd7634d2d1f6b4f (diff) | |
| parent | 489e176c71f36654dcb8835926f7e5717b8b4c19 (diff) | |
Merge branch 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci
* 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci: (50 commits)
davinci: fix remaining board support after io_pgoffst removal
davinci: mityomapl138: make file local data static
arm/davinci: remove duplicated include
davinci: Initial support for Omapl138-Hawkboard
davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom
davinci: add tnetv107x touchscreen platform device
input: add driver for tnetv107x touchscreen controller
davinci: add keypad config for tnetv107x evm board
davinci: add tnetv107x keypad platform device
input: add driver for tnetv107x on-chip keypad controller
net: davinci_emac: cleanup unused cpdma code
net: davinci_emac: switch to new cpdma layer
net: davinci_emac: separate out cpdma code
net: davinci_emac: cleanup unused mdio emac code
omap: cleanup unused davinci mdio arch code
davinci: cleanup mdio arch code and switch to phy_id
net: davinci_emac: switch to new mdio
omap: add mdio platform devices
davinci: add mdio platform devices
net: davinci_emac: separate out davinci mdio
...
Fix up trivial conflict in drivers/input/keyboard/Kconfig (two entries
added next to each other - one from the davinci merge, one from the
input merge)
51 files changed, 3810 insertions, 1359 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8f72c90aec0f..541451050b36 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -5388,8 +5388,8 @@ F: drivers/*/*s3c2410* | |||
| 5388 | F: drivers/*/*/*s3c2410* | 5388 | F: drivers/*/*/*s3c2410* |
| 5389 | 5389 | ||
| 5390 | TI DAVINCI MACHINE SUPPORT | 5390 | TI DAVINCI MACHINE SUPPORT |
| 5391 | P: Kevin Hilman | 5391 | M: Kevin Hilman <khilman@deeprootsystems.com> |
| 5392 | M: davinci-linux-open-source@linux.davincidsp.com | 5392 | L: davinci-linux-open-source@linux.davincidsp.com (subscribers-only) |
| 5393 | Q: http://patchwork.kernel.org/project/linux-davinci/list/ | 5393 | Q: http://patchwork.kernel.org/project/linux-davinci/list/ |
| 5394 | S: Supported | 5394 | S: Supported |
| 5395 | F: arch/arm/mach-davinci | 5395 | F: arch/arm/mach-davinci |
diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index ba6670556f78..cdc40c4b8c48 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig | |||
| @@ -17,6 +17,8 @@ CONFIG_MODVERSIONS=y | |||
| 17 | CONFIG_ARCH_DAVINCI=y | 17 | CONFIG_ARCH_DAVINCI=y |
| 18 | CONFIG_ARCH_DAVINCI_DA830=y | 18 | CONFIG_ARCH_DAVINCI_DA830=y |
| 19 | CONFIG_ARCH_DAVINCI_DA850=y | 19 | CONFIG_ARCH_DAVINCI_DA850=y |
| 20 | CONFIG_MACH_MITYOMAPL138=y | ||
| 21 | CONFIG_MACH_OMAPL138_HAWKBOARD=y | ||
| 20 | CONFIG_DAVINCI_RESET_CLOCKS=y | 22 | CONFIG_DAVINCI_RESET_CLOCKS=y |
| 21 | CONFIG_NO_HZ=y | 23 | CONFIG_NO_HZ=y |
| 22 | CONFIG_HIGH_RES_TIMERS=y | 24 | CONFIG_HIGH_RES_TIMERS=y |
| @@ -79,6 +81,7 @@ CONFIG_I2C_DAVINCI=y | |||
| 79 | # CONFIG_HWMON is not set | 81 | # CONFIG_HWMON is not set |
| 80 | CONFIG_WATCHDOG=y | 82 | CONFIG_WATCHDOG=y |
| 81 | CONFIG_REGULATOR=y | 83 | CONFIG_REGULATOR=y |
| 84 | CONFIG_REGULATOR_DUMMY=y | ||
| 82 | CONFIG_REGULATOR_TPS6507X=y | 85 | CONFIG_REGULATOR_TPS6507X=y |
| 83 | CONFIG_FB=y | 86 | CONFIG_FB=y |
| 84 | CONFIG_FB_DA8XX=y | 87 | CONFIG_FB_DA8XX=y |
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 71f90f864748..b77b860b36d7 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig | |||
| @@ -20,23 +20,23 @@ config ARCH_DAVINCI_DM644x | |||
| 20 | select ARCH_DAVINCI_DMx | 20 | select ARCH_DAVINCI_DMx |
| 21 | 21 | ||
| 22 | config ARCH_DAVINCI_DM355 | 22 | config ARCH_DAVINCI_DM355 |
| 23 | bool "DaVinci 355 based system" | 23 | bool "DaVinci 355 based system" |
| 24 | select AINTC | 24 | select AINTC |
| 25 | select ARCH_DAVINCI_DMx | 25 | select ARCH_DAVINCI_DMx |
| 26 | 26 | ||
| 27 | config ARCH_DAVINCI_DM646x | 27 | config ARCH_DAVINCI_DM646x |
| 28 | bool "DaVinci 646x based system" | 28 | bool "DaVinci 646x based system" |
| 29 | select AINTC | 29 | select AINTC |
| 30 | select ARCH_DAVINCI_DMx | 30 | select ARCH_DAVINCI_DMx |
| 31 | 31 | ||
| 32 | config ARCH_DAVINCI_DA830 | 32 | config ARCH_DAVINCI_DA830 |
| 33 | bool "DA830/OMAP-L137 based system" | 33 | bool "DA830/OMAP-L137/AM17x based system" |
| 34 | select CP_INTC | 34 | select CP_INTC |
| 35 | select ARCH_DAVINCI_DA8XX | 35 | select ARCH_DAVINCI_DA8XX |
| 36 | select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1 | 36 | select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1 |
| 37 | 37 | ||
| 38 | config ARCH_DAVINCI_DA850 | 38 | config ARCH_DAVINCI_DA850 |
| 39 | bool "DA850/OMAP-L138 based system" | 39 | bool "DA850/OMAP-L138/AM18x based system" |
| 40 | select CP_INTC | 40 | select CP_INTC |
| 41 | select ARCH_DAVINCI_DA8XX | 41 | select ARCH_DAVINCI_DA8XX |
| 42 | select ARCH_HAS_CPUFREQ | 42 | select ARCH_HAS_CPUFREQ |
| @@ -115,21 +115,21 @@ config MACH_DAVINCI_DM365_EVM | |||
| 115 | for development is a DM365 EVM | 115 | for development is a DM365 EVM |
| 116 | 116 | ||
| 117 | config MACH_DAVINCI_DA830_EVM | 117 | config MACH_DAVINCI_DA830_EVM |
| 118 | bool "TI DA830/OMAP-L137 Reference Platform" | 118 | bool "TI DA830/OMAP-L137/AM17x Reference Platform" |
| 119 | default ARCH_DAVINCI_DA830 | 119 | default ARCH_DAVINCI_DA830 |
| 120 | depends on ARCH_DAVINCI_DA830 | 120 | depends on ARCH_DAVINCI_DA830 |
| 121 | select GPIO_PCF857X | 121 | select GPIO_PCF857X |
| 122 | help | 122 | help |
| 123 | Say Y here to select the TI DA830/OMAP-L137 Evaluation Module. | 123 | Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module. |
| 124 | 124 | ||
| 125 | choice | 125 | choice |
| 126 | prompt "Select DA830/OMAP-L137 UI board peripheral" | 126 | prompt "Select DA830/OMAP-L137/AM17x UI board peripheral" |
| 127 | depends on MACH_DAVINCI_DA830_EVM | 127 | depends on MACH_DAVINCI_DA830_EVM |
| 128 | help | 128 | help |
| 129 | The presence of UI card on the DA830/OMAP-L137 EVM is detected | 129 | The presence of UI card on the DA830/OMAP-L137/AM17x EVM is |
| 130 | automatically based on successful probe of the I2C based GPIO | 130 | detected automatically based on successful probe of the I2C |
| 131 | expander on that board. This option selected in this menu has | 131 | based GPIO expander on that board. This option selected in this |
| 132 | an effect only in case of a successful UI card detection. | 132 | menu has an effect only in case of a successful UI card detection. |
| 133 | 133 | ||
| 134 | config DA830_UI_LCD | 134 | config DA830_UI_LCD |
| 135 | bool "LCD" | 135 | bool "LCD" |
| @@ -140,23 +140,23 @@ config DA830_UI_LCD | |||
| 140 | config DA830_UI_NAND | 140 | config DA830_UI_NAND |
| 141 | bool "NAND flash" | 141 | bool "NAND flash" |
| 142 | help | 142 | help |
| 143 | Say Y here to use the NAND flash. Do not forget to setup | 143 | Say Y here to use the NAND flash. Do not forget to setup |
| 144 | the switch correctly. | 144 | the switch correctly. |
| 145 | endchoice | 145 | endchoice |
| 146 | 146 | ||
| 147 | config MACH_DAVINCI_DA850_EVM | 147 | config MACH_DAVINCI_DA850_EVM |
| 148 | bool "TI DA850/OMAP-L138 Reference Platform" | 148 | bool "TI DA850/OMAP-L138/AM18x Reference Platform" |
| 149 | default ARCH_DAVINCI_DA850 | 149 | default ARCH_DAVINCI_DA850 |
| 150 | depends on ARCH_DAVINCI_DA850 | 150 | depends on ARCH_DAVINCI_DA850 |
| 151 | select GPIO_PCA953X | 151 | select GPIO_PCA953X |
| 152 | help | 152 | help |
| 153 | Say Y here to select the TI DA850/OMAP-L138 Evaluation Module. | 153 | Say Y here to select the TI DA850/OMAP-L138/AM18x Evaluation Module. |
| 154 | 154 | ||
| 155 | choice | 155 | choice |
| 156 | prompt "Select peripherals connected to expander on UI board" | 156 | prompt "Select peripherals connected to expander on UI board" |
| 157 | depends on MACH_DAVINCI_DA850_EVM | 157 | depends on MACH_DAVINCI_DA850_EVM |
| 158 | help | 158 | help |
| 159 | The presence of User Interface (UI) card on the DA850/OMAP-L138 | 159 | The presence of User Interface (UI) card on the DA850/OMAP-L138/AM18x |
| 160 | EVM is detected automatically based on successful probe of the I2C | 160 | EVM is detected automatically based on successful probe of the I2C |
| 161 | based GPIO expander on that card. This option selected in this | 161 | based GPIO expander on that card. This option selected in this |
| 162 | menu has an effect only in case of a successful UI card detection. | 162 | menu has an effect only in case of a successful UI card detection. |
| @@ -165,13 +165,13 @@ config DA850_UI_NONE | |||
| 165 | bool "No peripheral is enabled" | 165 | bool "No peripheral is enabled" |
| 166 | help | 166 | help |
| 167 | Say Y if you do not want to enable any of the peripherals connected | 167 | Say Y if you do not want to enable any of the peripherals connected |
| 168 | to TCA6416 expander on DA850/OMAP-L138 EVM UI card | 168 | to TCA6416 expander on DA850/OMAP-L138/AM18x EVM UI card |
| 169 | 169 | ||
| 170 | config DA850_UI_RMII | 170 | config DA850_UI_RMII |
| 171 | bool "RMII Ethernet PHY" | 171 | bool "RMII Ethernet PHY" |
| 172 | help | 172 | help |
| 173 | Say Y if you want to use the RMII PHY on the DA850/OMAP-L138 EVM. | 173 | Say Y if you want to use the RMII PHY on the DA850/OMAP-L138/AM18x |
| 174 | This PHY is found on the UI daughter card that is supplied with | 174 | EVM. This PHY is found on the UI daughter card that is supplied with |
| 175 | the EVM. | 175 | the EVM. |
| 176 | NOTE: Please take care while choosing this option, MII PHY will | 176 | NOTE: Please take care while choosing this option, MII PHY will |
| 177 | not be functional if RMII mode is selected. | 177 | not be functional if RMII mode is selected. |
| @@ -185,6 +185,22 @@ config MACH_TNETV107X | |||
| 185 | help | 185 | help |
| 186 | Say Y here to select the TI TNETV107X Evaluation Module. | 186 | Say Y here to select the TI TNETV107X Evaluation Module. |
| 187 | 187 | ||
| 188 | config MACH_MITYOMAPL138 | ||
| 189 | bool "Critical Link MityDSP-L138/MityARM-1808 SoM" | ||
| 190 | depends on ARCH_DAVINCI_DA850 | ||
| 191 | help | ||
| 192 | Say Y here to select the Critical Link MityDSP-L138/MityARM-1808 | ||
| 193 | System on Module. Information on this SoM may be found at | ||
| 194 | http://www.mitydsp.com | ||
| 195 | |||
| 196 | config MACH_OMAPL138_HAWKBOARD | ||
| 197 | bool "TI AM1808 / OMAPL-138 Hawkboard platform" | ||
| 198 | depends on ARCH_DAVINCI_DA850 | ||
| 199 | help | ||
| 200 | Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . | ||
| 201 | Information of this board may be found at | ||
| 202 | http://www.hawkboard.org/ | ||
| 203 | |||
| 188 | config DAVINCI_MUX | 204 | config DAVINCI_MUX |
| 189 | bool "DAVINCI multiplexing support" | 205 | bool "DAVINCI multiplexing support" |
| 190 | depends on ARCH_DAVINCI | 206 | depends on ARCH_DAVINCI |
| @@ -195,20 +211,20 @@ config DAVINCI_MUX | |||
| 195 | say Y. | 211 | say Y. |
| 196 | 212 | ||
| 197 | config DAVINCI_MUX_DEBUG | 213 | config DAVINCI_MUX_DEBUG |
| 198 | bool "Multiplexing debug output" | 214 | bool "Multiplexing debug output" |
| 199 | depends on DAVINCI_MUX | 215 | depends on DAVINCI_MUX |
| 200 | help | 216 | help |
| 201 | Makes the multiplexing functions print out a lot of debug info. | 217 | Makes the multiplexing functions print out a lot of debug info. |
| 202 | This is useful if you want to find out the correct values of the | 218 | This is useful if you want to find out the correct values of the |
| 203 | multiplexing registers. | 219 | multiplexing registers. |
| 204 | 220 | ||
| 205 | config DAVINCI_MUX_WARNINGS | 221 | config DAVINCI_MUX_WARNINGS |
| 206 | bool "Warn about pins the bootloader didn't set up" | 222 | bool "Warn about pins the bootloader didn't set up" |
| 207 | depends on DAVINCI_MUX | 223 | depends on DAVINCI_MUX |
| 208 | help | 224 | help |
| 209 | Choose Y here to warn whenever driver initialization logic needs | 225 | Choose Y here to warn whenever driver initialization logic needs |
| 210 | to change the pin multiplexing setup. When there are no warnings | 226 | to change the pin multiplexing setup. When there are no warnings |
| 211 | printed, it's safe to deselect DAVINCI_MUX for your product. | 227 | printed, it's safe to deselect DAVINCI_MUX for your product. |
| 212 | 228 | ||
| 213 | config DAVINCI_RESET_CLOCKS | 229 | config DAVINCI_RESET_CLOCKS |
| 214 | bool "Reset unused clocks during boot" | 230 | bool "Reset unused clocks during boot" |
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index eab4c0fd667a..0b87a1ca2bb3 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | # Common objects | 6 | # Common objects |
| 7 | obj-y := time.o clock.o serial.o io.o psc.o \ | 7 | obj-y := time.o clock.o serial.o io.o psc.o \ |
| 8 | gpio.o dma.o usb.o common.o sram.o | 8 | gpio.o dma.o usb.o common.o sram.o aemif.o |
| 9 | 9 | ||
| 10 | obj-$(CONFIG_DAVINCI_MUX) += mux.o | 10 | obj-$(CONFIG_DAVINCI_MUX) += mux.o |
| 11 | 11 | ||
| @@ -33,6 +33,8 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o | |||
| 33 | obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o | 33 | obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o |
| 34 | obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o | 34 | obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o |
| 35 | obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o | 35 | obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o |
| 36 | obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o | ||
| 37 | obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o | ||
| 36 | 38 | ||
| 37 | # Power Management | 39 | # Power Management |
| 38 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | 40 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o |
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c new file mode 100644 index 000000000000..9c3f500fc12f --- /dev/null +++ b/arch/arm/mach-davinci/aemif.c | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | /* | ||
| 2 | * AEMIF support for DaVinci SoCs | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Texas Instruments Incorporated. http://www.ti.com/ | ||
| 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 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/clk.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/time.h> | ||
| 17 | |||
| 18 | #include <mach/aemif.h> | ||
| 19 | |||
| 20 | /* Timing value configuration */ | ||
| 21 | |||
| 22 | #define TA(x) ((x) << 2) | ||
| 23 | #define RHOLD(x) ((x) << 4) | ||
| 24 | #define RSTROBE(x) ((x) << 7) | ||
| 25 | #define RSETUP(x) ((x) << 13) | ||
| 26 | #define WHOLD(x) ((x) << 17) | ||
| 27 | #define WSTROBE(x) ((x) << 20) | ||
| 28 | #define WSETUP(x) ((x) << 26) | ||
| 29 | |||
| 30 | #define TA_MAX 0x3 | ||
| 31 | #define RHOLD_MAX 0x7 | ||
| 32 | #define RSTROBE_MAX 0x3f | ||
| 33 | #define RSETUP_MAX 0xf | ||
| 34 | #define WHOLD_MAX 0x7 | ||
| 35 | #define WSTROBE_MAX 0x3f | ||
| 36 | #define WSETUP_MAX 0xf | ||
| 37 | |||
| 38 | #define TIMING_MASK (TA(TA_MAX) | \ | ||
| 39 | RHOLD(RHOLD_MAX) | \ | ||
| 40 | RSTROBE(RSTROBE_MAX) | \ | ||
| 41 | RSETUP(RSETUP_MAX) | \ | ||
| 42 | WHOLD(WHOLD_MAX) | \ | ||
| 43 | WSTROBE(WSTROBE_MAX) | \ | ||
| 44 | WSETUP(WSETUP_MAX)) | ||
| 45 | |||
| 46 | /* | ||
| 47 | * aemif_calc_rate - calculate timing data. | ||
| 48 | * @wanted: The cycle time needed in nanoseconds. | ||
| 49 | * @clk: The input clock rate in kHz. | ||
| 50 | * @max: The maximum divider value that can be programmed. | ||
| 51 | * | ||
| 52 | * On success, returns the calculated timing value minus 1 for easy | ||
| 53 | * programming into AEMIF timing registers, else negative errno. | ||
| 54 | */ | ||
| 55 | static int aemif_calc_rate(int wanted, unsigned long clk, int max) | ||
| 56 | { | ||
| 57 | int result; | ||
| 58 | |||
| 59 | result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1; | ||
| 60 | |||
| 61 | pr_debug("%s: result %d from %ld, %d\n", __func__, result, clk, wanted); | ||
| 62 | |||
| 63 | /* It is generally OK to have a more relaxed timing than requested... */ | ||
| 64 | if (result < 0) | ||
| 65 | result = 0; | ||
| 66 | |||
| 67 | /* ... But configuring tighter timings is not an option. */ | ||
| 68 | else if (result > max) | ||
| 69 | result = -EINVAL; | ||
| 70 | |||
| 71 | return result; | ||
| 72 | } | ||
| 73 | |||
| 74 | /** | ||
| 75 | * davinci_aemif_setup_timing - setup timing values for a given AEMIF interface | ||
| 76 | * @t: timing values to be progammed | ||
| 77 | * @base: The virtual base address of the AEMIF interface | ||
| 78 | * @cs: chip-select to program the timing values for | ||
| 79 | * | ||
| 80 | * This function programs the given timing values (in real clock) into the | ||
| 81 | * AEMIF registers taking the AEMIF clock into account. | ||
| 82 | * | ||
| 83 | * This function does not use any locking while programming the AEMIF | ||
| 84 | * because it is expected that there is only one user of a given | ||
| 85 | * chip-select. | ||
| 86 | * | ||
| 87 | * Returns 0 on success, else negative errno. | ||
| 88 | */ | ||
| 89 | int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, | ||
| 90 | void __iomem *base, unsigned cs) | ||
| 91 | { | ||
| 92 | unsigned set, val; | ||
| 93 | unsigned ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup; | ||
| 94 | unsigned offset = A1CR_OFFSET + cs * 4; | ||
| 95 | struct clk *aemif_clk; | ||
| 96 | unsigned long clkrate; | ||
| 97 | |||
| 98 | if (!t) | ||
| 99 | return 0; /* Nothing to do */ | ||
| 100 | |||
| 101 | aemif_clk = clk_get(NULL, "aemif"); | ||
| 102 | if (IS_ERR(aemif_clk)) | ||
| 103 | return PTR_ERR(aemif_clk); | ||
| 104 | |||
| 105 | clkrate = clk_get_rate(aemif_clk); | ||
| 106 | |||
| 107 | clkrate /= 1000; /* turn clock into kHz for ease of use */ | ||
| 108 | |||
| 109 | ta = aemif_calc_rate(t->ta, clkrate, TA_MAX); | ||
| 110 | rhold = aemif_calc_rate(t->rhold, clkrate, RHOLD_MAX); | ||
| 111 | rstrobe = aemif_calc_rate(t->rstrobe, clkrate, RSTROBE_MAX); | ||
| 112 | rsetup = aemif_calc_rate(t->rsetup, clkrate, RSETUP_MAX); | ||
| 113 | whold = aemif_calc_rate(t->whold, clkrate, WHOLD_MAX); | ||
| 114 | wstrobe = aemif_calc_rate(t->wstrobe, clkrate, WSTROBE_MAX); | ||
| 115 | wsetup = aemif_calc_rate(t->wsetup, clkrate, WSETUP_MAX); | ||
| 116 | |||
| 117 | if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 || | ||
| 118 | whold < 0 || wstrobe < 0 || wsetup < 0) { | ||
| 119 | pr_err("%s: cannot get suitable timings\n", __func__); | ||
| 120 | return -EINVAL; | ||
| 121 | } | ||
| 122 | |||
| 123 | set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) | | ||
| 124 | WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup); | ||
| 125 | |||
| 126 | val = __raw_readl(base + offset); | ||
| 127 | val &= ~TIMING_MASK; | ||
| 128 | val |= set; | ||
| 129 | __raw_writel(val, base + offset); | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | EXPORT_SYMBOL(davinci_aemif_setup_timing); | ||
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 7f3cdbfc0fbb..b52a3a1abd94 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c | |||
| @@ -29,10 +29,9 @@ | |||
| 29 | #include <mach/nand.h> | 29 | #include <mach/nand.h> |
| 30 | #include <mach/da8xx.h> | 30 | #include <mach/da8xx.h> |
| 31 | #include <mach/usb.h> | 31 | #include <mach/usb.h> |
| 32 | #include <mach/aemif.h> | ||
| 32 | 33 | ||
| 33 | #define DA830_EVM_PHY_MASK 0x0 | 34 | #define DA830_EVM_PHY_ID "" |
| 34 | #define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ | ||
| 35 | |||
| 36 | /* | 35 | /* |
| 37 | * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. | 36 | * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. |
| 38 | */ | 37 | */ |
| @@ -360,6 +359,16 @@ static struct nand_bbt_descr da830_evm_nand_bbt_mirror_descr = { | |||
| 360 | .pattern = da830_evm_nand_mirror_pattern | 359 | .pattern = da830_evm_nand_mirror_pattern |
| 361 | }; | 360 | }; |
| 362 | 361 | ||
| 362 | static struct davinci_aemif_timing da830_evm_nandflash_timing = { | ||
| 363 | .wsetup = 24, | ||
| 364 | .wstrobe = 21, | ||
| 365 | .whold = 14, | ||
| 366 | .rsetup = 19, | ||
| 367 | .rstrobe = 50, | ||
| 368 | .rhold = 0, | ||
| 369 | .ta = 20, | ||
| 370 | }; | ||
| 371 | |||
| 363 | static struct davinci_nand_pdata da830_evm_nand_pdata = { | 372 | static struct davinci_nand_pdata da830_evm_nand_pdata = { |
| 364 | .parts = da830_evm_nand_partitions, | 373 | .parts = da830_evm_nand_partitions, |
| 365 | .nr_parts = ARRAY_SIZE(da830_evm_nand_partitions), | 374 | .nr_parts = ARRAY_SIZE(da830_evm_nand_partitions), |
| @@ -368,6 +377,7 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = { | |||
| 368 | .options = NAND_USE_FLASH_BBT, | 377 | .options = NAND_USE_FLASH_BBT, |
| 369 | .bbt_td = &da830_evm_nand_bbt_main_descr, | 378 | .bbt_td = &da830_evm_nand_bbt_main_descr, |
| 370 | .bbt_md = &da830_evm_nand_bbt_mirror_descr, | 379 | .bbt_md = &da830_evm_nand_bbt_mirror_descr, |
| 380 | .timing = &da830_evm_nandflash_timing, | ||
| 371 | }; | 381 | }; |
| 372 | 382 | ||
| 373 | static struct resource da830_evm_nand_resources[] = { | 383 | static struct resource da830_evm_nand_resources[] = { |
| @@ -546,9 +556,8 @@ static __init void da830_evm_init(void) | |||
| 546 | 556 | ||
| 547 | da830_evm_usb_init(); | 557 | da830_evm_usb_init(); |
| 548 | 558 | ||
| 549 | soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK; | ||
| 550 | soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY; | ||
| 551 | soc_info->emac_pdata->rmii_en = 1; | 559 | soc_info->emac_pdata->rmii_en = 1; |
| 560 | soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID; | ||
| 552 | 561 | ||
| 553 | ret = davinci_cfg_reg_list(da830_cpgmac_pins); | 562 | ret = davinci_cfg_reg_list(da830_cpgmac_pins); |
| 554 | if (ret) | 563 | if (ret) |
| @@ -586,6 +595,9 @@ static __init void da830_evm_init(void) | |||
| 586 | #ifdef CONFIG_SERIAL_8250_CONSOLE | 595 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
| 587 | static int __init da830_evm_console_init(void) | 596 | static int __init da830_evm_console_init(void) |
| 588 | { | 597 | { |
| 598 | if (!machine_is_davinci_da830_evm()) | ||
| 599 | return 0; | ||
| 600 | |||
| 589 | return add_preferred_console("ttyS", 2, "115200"); | 601 | return add_preferred_console("ttyS", 2, "115200"); |
| 590 | } | 602 | } |
| 591 | console_initcall(da830_evm_console_init); | 603 | console_initcall(da830_evm_console_init); |
| @@ -596,7 +608,7 @@ static void __init da830_evm_map_io(void) | |||
| 596 | da830_init(); | 608 | da830_init(); |
| 597 | } | 609 | } |
| 598 | 610 | ||
| 599 | MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM") | 611 | MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM") |
| 600 | .boot_params = (DA8XX_DDR_BASE + 0x100), | 612 | .boot_params = (DA8XX_DDR_BASE + 0x100), |
| 601 | .map_io = da830_evm_map_io, | 613 | .map_io = da830_evm_map_io, |
| 602 | .init_irq = cp_intc_init, | 614 | .init_irq = cp_intc_init, |
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index b26f5cbfce3e..c6e11c682e4c 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/mtd/physmap.h> | 26 | #include <linux/mtd/physmap.h> |
| 27 | #include <linux/regulator/machine.h> | 27 | #include <linux/regulator/machine.h> |
| 28 | #include <linux/regulator/tps6507x.h> | 28 | #include <linux/regulator/tps6507x.h> |
| 29 | #include <linux/mfd/tps6507x.h> | ||
| 30 | #include <linux/input/tps6507x-ts.h> | 29 | #include <linux/input/tps6507x-ts.h> |
| 31 | 30 | ||
| 32 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
| @@ -36,10 +35,9 @@ | |||
| 36 | #include <mach/da8xx.h> | 35 | #include <mach/da8xx.h> |
| 37 | #include <mach/nand.h> | 36 | #include <mach/nand.h> |
| 38 | #include <mach/mux.h> | 37 | #include <mach/mux.h> |
| 38 | #include <mach/aemif.h> | ||
| 39 | 39 | ||
| 40 | #define DA850_EVM_PHY_MASK 0x1 | 40 | #define DA850_EVM_PHY_ID "0:00" |
| 41 | #define DA850_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ | ||
| 42 | |||
| 43 | #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) | 41 | #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) |
| 44 | #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) | 42 | #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) |
| 45 | 43 | ||
| @@ -110,7 +108,7 @@ static struct platform_device da850_pm_device = { | |||
| 110 | * to boot, using TI's tools to install the secondary boot loader | 108 | * to boot, using TI's tools to install the secondary boot loader |
| 111 | * (UBL) and U-Boot. | 109 | * (UBL) and U-Boot. |
| 112 | */ | 110 | */ |
| 113 | struct mtd_partition da850_evm_nandflash_partition[] = { | 111 | static struct mtd_partition da850_evm_nandflash_partition[] = { |
| 114 | { | 112 | { |
| 115 | .name = "u-boot env", | 113 | .name = "u-boot env", |
| 116 | .offset = 0, | 114 | .offset = 0, |
| @@ -143,12 +141,23 @@ struct mtd_partition da850_evm_nandflash_partition[] = { | |||
| 143 | }, | 141 | }, |
| 144 | }; | 142 | }; |
| 145 | 143 | ||
| 144 | static struct davinci_aemif_timing da850_evm_nandflash_timing = { | ||
| 145 | .wsetup = 24, | ||
| 146 | .wstrobe = 21, | ||
| 147 | .whold = 14, | ||
| 148 | .rsetup = 19, | ||
| 149 | .rstrobe = 50, | ||
| 150 | .rhold = 0, | ||
| 151 | .ta = 20, | ||
| 152 | }; | ||
| 153 | |||
| 146 | static struct davinci_nand_pdata da850_evm_nandflash_data = { | 154 | static struct davinci_nand_pdata da850_evm_nandflash_data = { |
| 147 | .parts = da850_evm_nandflash_partition, | 155 | .parts = da850_evm_nandflash_partition, |
| 148 | .nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition), | 156 | .nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition), |
| 149 | .ecc_mode = NAND_ECC_HW, | 157 | .ecc_mode = NAND_ECC_HW, |
| 150 | .ecc_bits = 4, | 158 | .ecc_bits = 4, |
| 151 | .options = NAND_USE_FLASH_BBT, | 159 | .options = NAND_USE_FLASH_BBT, |
| 160 | .timing = &da850_evm_nandflash_timing, | ||
| 152 | }; | 161 | }; |
| 153 | 162 | ||
| 154 | static struct resource da850_evm_nandflash_resource[] = { | 163 | static struct resource da850_evm_nandflash_resource[] = { |
| @@ -196,6 +205,30 @@ static void __init da850_evm_init_nor(void) | |||
| 196 | iounmap(aemif_addr); | 205 | iounmap(aemif_addr); |
| 197 | } | 206 | } |
| 198 | 207 | ||
| 208 | static const short da850_evm_nand_pins[] = { | ||
| 209 | DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3, | ||
| 210 | DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7, | ||
| 211 | DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4, | ||
| 212 | DA850_NEMA_WE, DA850_NEMA_OE, | ||
| 213 | -1 | ||
| 214 | }; | ||
| 215 | |||
| 216 | static const short da850_evm_nor_pins[] = { | ||
| 217 | DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2, | ||
| 218 | DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1, | ||
| 219 | DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5, | ||
| 220 | DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9, | ||
| 221 | DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13, | ||
| 222 | DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1, | ||
| 223 | DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5, | ||
| 224 | DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9, | ||
| 225 | DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13, | ||
| 226 | DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17, | ||
| 227 | DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21, | ||
| 228 | DA850_EMA_A_22, DA850_EMA_A_23, | ||
| 229 | -1 | ||
| 230 | }; | ||
| 231 | |||
| 199 | static u32 ui_card_detected; | 232 | static u32 ui_card_detected; |
| 200 | 233 | ||
| 201 | #if defined(CONFIG_MMC_DAVINCI) || \ | 234 | #if defined(CONFIG_MMC_DAVINCI) || \ |
| @@ -205,17 +238,17 @@ static u32 ui_card_detected; | |||
| 205 | #define HAS_MMC 0 | 238 | #define HAS_MMC 0 |
| 206 | #endif | 239 | #endif |
| 207 | 240 | ||
| 208 | static __init void da850_evm_setup_nor_nand(void) | 241 | static inline void da850_evm_setup_nor_nand(void) |
| 209 | { | 242 | { |
| 210 | int ret = 0; | 243 | int ret = 0; |
| 211 | 244 | ||
| 212 | if (ui_card_detected & !HAS_MMC) { | 245 | if (ui_card_detected & !HAS_MMC) { |
| 213 | ret = davinci_cfg_reg_list(da850_nand_pins); | 246 | ret = davinci_cfg_reg_list(da850_evm_nand_pins); |
| 214 | if (ret) | 247 | if (ret) |
| 215 | pr_warning("da850_evm_init: nand mux setup failed: " | 248 | pr_warning("da850_evm_init: nand mux setup failed: " |
| 216 | "%d\n", ret); | 249 | "%d\n", ret); |
| 217 | 250 | ||
| 218 | ret = davinci_cfg_reg_list(da850_nor_pins); | 251 | ret = davinci_cfg_reg_list(da850_evm_nor_pins); |
| 219 | if (ret) | 252 | if (ret) |
| 220 | pr_warning("da850_evm_init: nor mux setup failed: %d\n", | 253 | pr_warning("da850_evm_init: nor mux setup failed: %d\n", |
| 221 | ret); | 254 | ret); |
| @@ -406,7 +439,7 @@ static int da850_lcd_hw_init(void) | |||
| 406 | /* TPS65070 voltage regulator support */ | 439 | /* TPS65070 voltage regulator support */ |
| 407 | 440 | ||
| 408 | /* 3.3V */ | 441 | /* 3.3V */ |
| 409 | struct regulator_consumer_supply tps65070_dcdc1_consumers[] = { | 442 | static struct regulator_consumer_supply tps65070_dcdc1_consumers[] = { |
| 410 | { | 443 | { |
| 411 | .supply = "usb0_vdda33", | 444 | .supply = "usb0_vdda33", |
| 412 | }, | 445 | }, |
| @@ -416,7 +449,7 @@ struct regulator_consumer_supply tps65070_dcdc1_consumers[] = { | |||
| 416 | }; | 449 | }; |
| 417 | 450 | ||
| 418 | /* 3.3V or 1.8V */ | 451 | /* 3.3V or 1.8V */ |
| 419 | struct regulator_consumer_supply tps65070_dcdc2_consumers[] = { | 452 | static struct regulator_consumer_supply tps65070_dcdc2_consumers[] = { |
| 420 | { | 453 | { |
| 421 | .supply = "dvdd3318_a", | 454 | .supply = "dvdd3318_a", |
| 422 | }, | 455 | }, |
| @@ -429,14 +462,14 @@ struct regulator_consumer_supply tps65070_dcdc2_consumers[] = { | |||
| 429 | }; | 462 | }; |
| 430 | 463 | ||
| 431 | /* 1.2V */ | 464 | /* 1.2V */ |
| 432 | struct regulator_consumer_supply tps65070_dcdc3_consumers[] = { | 465 | static struct regulator_consumer_supply tps65070_dcdc3_consumers[] = { |
| 433 | { | 466 | { |
| 434 | .supply = "cvdd", | 467 | .supply = "cvdd", |
| 435 | }, | 468 | }, |
| 436 | }; | 469 | }; |
| 437 | 470 | ||
| 438 | /* 1.8V LDO */ | 471 | /* 1.8V LDO */ |
| 439 | struct regulator_consumer_supply tps65070_ldo1_consumers[] = { | 472 | static struct regulator_consumer_supply tps65070_ldo1_consumers[] = { |
| 440 | { | 473 | { |
| 441 | .supply = "sata_vddr", | 474 | .supply = "sata_vddr", |
| 442 | }, | 475 | }, |
| @@ -452,7 +485,7 @@ struct regulator_consumer_supply tps65070_ldo1_consumers[] = { | |||
| 452 | }; | 485 | }; |
| 453 | 486 | ||
| 454 | /* 1.2V LDO */ | 487 | /* 1.2V LDO */ |
| 455 | struct regulator_consumer_supply tps65070_ldo2_consumers[] = { | 488 | static struct regulator_consumer_supply tps65070_ldo2_consumers[] = { |
| 456 | { | 489 | { |
| 457 | .supply = "sata_vdd", | 490 | .supply = "sata_vdd", |
| 458 | }, | 491 | }, |
| @@ -475,7 +508,7 @@ static struct tps6507x_reg_platform_data tps6507x_platform_data = { | |||
| 475 | .defdcdc_default = true, | 508 | .defdcdc_default = true, |
| 476 | }; | 509 | }; |
| 477 | 510 | ||
| 478 | struct regulator_init_data tps65070_regulator_data[] = { | 511 | static struct regulator_init_data tps65070_regulator_data[] = { |
| 479 | /* dcdc1 */ | 512 | /* dcdc1 */ |
| 480 | { | 513 | { |
| 481 | .constraints = { | 514 | .constraints = { |
| @@ -576,6 +609,23 @@ static const short da850_evm_lcdc_pins[] = { | |||
| 576 | -1 | 609 | -1 |
| 577 | }; | 610 | }; |
| 578 | 611 | ||
| 612 | static const short da850_evm_mii_pins[] = { | ||
| 613 | DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, | ||
| 614 | DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, | ||
| 615 | DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, | ||
| 616 | DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, | ||
| 617 | DA850_MDIO_D, | ||
| 618 | -1 | ||
| 619 | }; | ||
| 620 | |||
| 621 | static const short da850_evm_rmii_pins[] = { | ||
| 622 | DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, | ||
| 623 | DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, | ||
| 624 | DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, | ||
| 625 | DA850_MDIO_D, | ||
| 626 | -1 | ||
| 627 | }; | ||
| 628 | |||
| 579 | static int __init da850_evm_config_emac(void) | 629 | static int __init da850_evm_config_emac(void) |
| 580 | { | 630 | { |
| 581 | void __iomem *cfg_chip3_base; | 631 | void __iomem *cfg_chip3_base; |
| @@ -593,12 +643,12 @@ static int __init da850_evm_config_emac(void) | |||
| 593 | 643 | ||
| 594 | if (rmii_en) { | 644 | if (rmii_en) { |
| 595 | val |= BIT(8); | 645 | val |= BIT(8); |
| 596 | ret = davinci_cfg_reg_list(da850_rmii_pins); | 646 | ret = davinci_cfg_reg_list(da850_evm_rmii_pins); |
| 597 | pr_info("EMAC: RMII PHY configured, MII PHY will not be" | 647 | pr_info("EMAC: RMII PHY configured, MII PHY will not be" |
| 598 | " functional\n"); | 648 | " functional\n"); |
| 599 | } else { | 649 | } else { |
| 600 | val &= ~BIT(8); | 650 | val &= ~BIT(8); |
| 601 | ret = davinci_cfg_reg_list(da850_cpgmac_pins); | 651 | ret = davinci_cfg_reg_list(da850_evm_mii_pins); |
| 602 | pr_info("EMAC: MII PHY configured, RMII PHY will not be" | 652 | pr_info("EMAC: MII PHY configured, RMII PHY will not be" |
| 603 | " functional\n"); | 653 | " functional\n"); |
| 604 | } | 654 | } |
| @@ -625,8 +675,7 @@ static int __init da850_evm_config_emac(void) | |||
| 625 | /* Enable/Disable MII MDIO clock */ | 675 | /* Enable/Disable MII MDIO clock */ |
| 626 | gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); | 676 | gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); |
| 627 | 677 | ||
| 628 | soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK; | 678 | soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID; |
| 629 | soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY; | ||
| 630 | 679 | ||
| 631 | ret = da8xx_register_emac(); | 680 | ret = da8xx_register_emac(); |
| 632 | if (ret) | 681 | if (ret) |
| @@ -787,7 +836,7 @@ static __init void da850_evm_init(void) | |||
| 787 | if (ret) | 836 | if (ret) |
| 788 | pr_warning("da850_evm_init: rtc setup failed: %d\n", ret); | 837 | pr_warning("da850_evm_init: rtc setup failed: %d\n", ret); |
| 789 | 838 | ||
| 790 | ret = da850_register_cpufreq(); | 839 | ret = da850_register_cpufreq("pll0_sysclk3"); |
| 791 | if (ret) | 840 | if (ret) |
| 792 | pr_warning("da850_evm_init: cpufreq registration failed: %d\n", | 841 | pr_warning("da850_evm_init: cpufreq registration failed: %d\n", |
| 793 | ret); | 842 | ret); |
| @@ -806,6 +855,9 @@ static __init void da850_evm_init(void) | |||
| 806 | #ifdef CONFIG_SERIAL_8250_CONSOLE | 855 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
| 807 | static int __init da850_evm_console_init(void) | 856 | static int __init da850_evm_console_init(void) |
| 808 | { | 857 | { |
| 858 | if (!machine_is_davinci_da850_evm()) | ||
| 859 | return 0; | ||
| 860 | |||
| 809 | return add_preferred_console("ttyS", 2, "115200"); | 861 | return add_preferred_console("ttyS", 2, "115200"); |
| 810 | } | 862 | } |
| 811 | console_initcall(da850_evm_console_init); | 863 | console_initcall(da850_evm_console_init); |
| @@ -816,7 +868,7 @@ static void __init da850_evm_map_io(void) | |||
| 816 | da850_init(); | 868 | da850_init(); |
| 817 | } | 869 | } |
| 818 | 870 | ||
| 819 | MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM") | 871 | MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM") |
| 820 | .boot_params = (DA8XX_DDR_BASE + 0x100), | 872 | .boot_params = (DA8XX_DDR_BASE + 0x100), |
| 821 | .map_io = da850_evm_map_io, | 873 | .map_io = da850_evm_map_io, |
| 822 | .init_irq = cp_intc_init, | 874 | .init_irq = cp_intc_init, |
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 944a0cbaf5cb..c67f684ee3e5 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c | |||
| @@ -54,9 +54,7 @@ static inline int have_tvp7002(void) | |||
| 54 | return 0; | 54 | return 0; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | #define DM365_EVM_PHY_MASK (0x2) | 57 | #define DM365_EVM_PHY_ID "0:01" |
| 58 | #define DM365_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ | ||
| 59 | |||
| 60 | /* | 58 | /* |
| 61 | * A MAX-II CPLD is used for various board control functions. | 59 | * A MAX-II CPLD is used for various board control functions. |
| 62 | */ | 60 | */ |
| @@ -175,7 +173,9 @@ static struct at24_platform_data eeprom_info = { | |||
| 175 | .context = (void *)0x7f00, | 173 | .context = (void *)0x7f00, |
| 176 | }; | 174 | }; |
| 177 | 175 | ||
| 178 | static struct snd_platform_data dm365_evm_snd_data; | 176 | static struct snd_platform_data dm365_evm_snd_data = { |
| 177 | .asp_chan_q = EVENTQ_3, | ||
| 178 | }; | ||
| 179 | 179 | ||
| 180 | static struct i2c_board_info i2c_info[] = { | 180 | static struct i2c_board_info i2c_info[] = { |
| 181 | { | 181 | { |
| @@ -533,8 +533,7 @@ fail: | |||
| 533 | 533 | ||
| 534 | /* ... and ENET ... */ | 534 | /* ... and ENET ... */ |
| 535 | dm365evm_emac_configure(); | 535 | dm365evm_emac_configure(); |
| 536 | soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK; | 536 | soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID; |
| 537 | soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY; | ||
| 538 | resets &= ~BIT(3); | 537 | resets &= ~BIT(3); |
| 539 | 538 | ||
| 540 | /* ... and AIC33 */ | 539 | /* ... and AIC33 */ |
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index d59fba15ba8d..0ca90b834586 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c | |||
| @@ -37,10 +37,9 @@ | |||
| 37 | #include <mach/nand.h> | 37 | #include <mach/nand.h> |
| 38 | #include <mach/mmc.h> | 38 | #include <mach/mmc.h> |
| 39 | #include <mach/usb.h> | 39 | #include <mach/usb.h> |
| 40 | #include <mach/aemif.h> | ||
| 40 | 41 | ||
| 41 | #define DM644X_EVM_PHY_MASK (0x2) | 42 | #define DM644X_EVM_PHY_ID "0:01" |
| 42 | #define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ | ||
| 43 | |||
| 44 | #define LXT971_PHY_ID (0x001378e2) | 43 | #define LXT971_PHY_ID (0x001378e2) |
| 45 | #define LXT971_PHY_MASK (0xfffffff0) | 44 | #define LXT971_PHY_MASK (0xfffffff0) |
| 46 | 45 | ||
| @@ -137,11 +136,22 @@ static struct mtd_partition davinci_evm_nandflash_partition[] = { | |||
| 137 | */ | 136 | */ |
| 138 | }; | 137 | }; |
| 139 | 138 | ||
| 139 | static struct davinci_aemif_timing davinci_evm_nandflash_timing = { | ||
| 140 | .wsetup = 20, | ||
| 141 | .wstrobe = 40, | ||
| 142 | .whold = 20, | ||
| 143 | .rsetup = 10, | ||
| 144 | .rstrobe = 40, | ||
| 145 | .rhold = 10, | ||
| 146 | .ta = 40, | ||
| 147 | }; | ||
| 148 | |||
| 140 | static struct davinci_nand_pdata davinci_evm_nandflash_data = { | 149 | static struct davinci_nand_pdata davinci_evm_nandflash_data = { |
| 141 | .parts = davinci_evm_nandflash_partition, | 150 | .parts = davinci_evm_nandflash_partition, |
| 142 | .nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition), | 151 | .nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition), |
| 143 | .ecc_mode = NAND_ECC_HW, | 152 | .ecc_mode = NAND_ECC_HW, |
| 144 | .options = NAND_USE_FLASH_BBT, | 153 | .options = NAND_USE_FLASH_BBT, |
| 154 | .timing = &davinci_evm_nandflash_timing, | ||
| 145 | }; | 155 | }; |
| 146 | 156 | ||
| 147 | static struct resource davinci_evm_nandflash_resource[] = { | 157 | static struct resource davinci_evm_nandflash_resource[] = { |
| @@ -695,9 +705,7 @@ static __init void davinci_evm_init(void) | |||
| 695 | davinci_serial_init(&uart_config); | 705 | davinci_serial_init(&uart_config); |
| 696 | dm644x_init_asp(&dm644x_evm_snd_data); | 706 | dm644x_init_asp(&dm644x_evm_snd_data); |
| 697 | 707 | ||
| 698 | soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK; | 708 | soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID; |
| 699 | soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY; | ||
| 700 | |||
| 701 | /* Register the fixup for PHY on DaVinci */ | 709 | /* Register the fixup for PHY on DaVinci */ |
| 702 | phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, | 710 | phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, |
| 703 | davinci_phy_fixup); | 711 | davinci_phy_fixup); |
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 6890488fb92b..f6ac9ba74878 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <mach/nand.h> | 42 | #include <mach/nand.h> |
| 43 | #include <mach/clock.h> | 43 | #include <mach/clock.h> |
| 44 | #include <mach/cdce949.h> | 44 | #include <mach/cdce949.h> |
| 45 | #include <mach/aemif.h> | ||
| 45 | 46 | ||
| 46 | #include "clock.h" | 47 | #include "clock.h" |
| 47 | 48 | ||
| @@ -71,6 +72,16 @@ static struct mtd_partition davinci_nand_partitions[] = { | |||
| 71 | } | 72 | } |
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 75 | static struct davinci_aemif_timing dm6467tevm_nandflash_timing = { | ||
| 76 | .wsetup = 29, | ||
| 77 | .wstrobe = 24, | ||
| 78 | .whold = 14, | ||
| 79 | .rsetup = 19, | ||
| 80 | .rstrobe = 33, | ||
| 81 | .rhold = 0, | ||
| 82 | .ta = 29, | ||
| 83 | }; | ||
| 84 | |||
| 74 | static struct davinci_nand_pdata davinci_nand_data = { | 85 | static struct davinci_nand_pdata davinci_nand_data = { |
| 75 | .mask_cle = 0x80000, | 86 | .mask_cle = 0x80000, |
| 76 | .mask_ale = 0x40000, | 87 | .mask_ale = 0x40000, |
| @@ -718,9 +729,7 @@ static struct davinci_uart_config uart_config __initdata = { | |||
| 718 | .enabled_uarts = (1 << 0), | 729 | .enabled_uarts = (1 << 0), |
| 719 | }; | 730 | }; |
| 720 | 731 | ||
| 721 | #define DM646X_EVM_PHY_MASK (0x2) | 732 | #define DM646X_EVM_PHY_ID "0:01" |
| 722 | #define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ | ||
| 723 | |||
| 724 | /* | 733 | /* |
| 725 | * The following EDMA channels/slots are not being used by drivers (for | 734 | * The following EDMA channels/slots are not being used by drivers (for |
| 726 | * example: Timer, GPIO, UART events etc) on dm646x, hence they are being | 735 | * example: Timer, GPIO, UART events etc) on dm646x, hence they are being |
| @@ -763,6 +772,9 @@ static __init void evm_init(void) | |||
| 763 | dm646x_init_mcasp0(&dm646x_evm_snd_data[0]); | 772 | dm646x_init_mcasp0(&dm646x_evm_snd_data[0]); |
| 764 | dm646x_init_mcasp1(&dm646x_evm_snd_data[1]); | 773 | dm646x_init_mcasp1(&dm646x_evm_snd_data[1]); |
| 765 | 774 | ||
| 775 | if (machine_is_davinci_dm6467tevm()) | ||
| 776 | davinci_nand_data.timing = &dm6467tevm_nandflash_timing; | ||
| 777 | |||
| 766 | platform_device_register(&davinci_nand_device); | 778 | platform_device_register(&davinci_nand_device); |
| 767 | 779 | ||
| 768 | dm646x_init_edma(dm646x_edma_rsv); | 780 | dm646x_init_edma(dm646x_edma_rsv); |
| @@ -770,8 +782,7 @@ static __init void evm_init(void) | |||
| 770 | if (HAS_ATA) | 782 | if (HAS_ATA) |
| 771 | davinci_init_ide(); | 783 | davinci_init_ide(); |
| 772 | 784 | ||
| 773 | soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; | 785 | soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID; |
| 774 | soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; | ||
| 775 | } | 786 | } |
| 776 | 787 | ||
| 777 | #define DM646X_EVM_REF_FREQ 27000000 | 788 | #define DM646X_EVM_REF_FREQ 27000000 |
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c new file mode 100644 index 000000000000..0bb5f0ce4fdc --- /dev/null +++ b/arch/arm/mach-davinci/board-mityomapl138.c | |||
| @@ -0,0 +1,422 @@ | |||
| 1 | /* | ||
| 2 | * Critical Link MityOMAP-L138 SoM | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Critical Link LLC - http://www.criticallink.com | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public License | ||
| 7 | * version 2. This program is licensed "as is" without any warranty of | ||
| 8 | * any kind, whether express or implied. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/console.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/mtd/partitions.h> | ||
| 16 | #include <linux/regulator/machine.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/i2c/at24.h> | ||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | |||
| 21 | #include <asm/mach-types.h> | ||
| 22 | #include <asm/mach/arch.h> | ||
| 23 | #include <mach/common.h> | ||
| 24 | #include <mach/cp_intc.h> | ||
| 25 | #include <mach/da8xx.h> | ||
| 26 | #include <mach/nand.h> | ||
| 27 | #include <mach/mux.h> | ||
| 28 | |||
| 29 | #define MITYOMAPL138_PHY_ID "0:03" | ||
| 30 | |||
| 31 | #define FACTORY_CONFIG_MAGIC 0x012C0138 | ||
| 32 | #define FACTORY_CONFIG_VERSION 0x00010001 | ||
| 33 | |||
| 34 | /* Data Held in On-Board I2C device */ | ||
| 35 | struct factory_config { | ||
| 36 | u32 magic; | ||
| 37 | u32 version; | ||
| 38 | u8 mac[6]; | ||
| 39 | u32 fpga_type; | ||
| 40 | u32 spare; | ||
| 41 | u32 serialnumber; | ||
| 42 | char partnum[32]; | ||
| 43 | }; | ||
| 44 | |||
| 45 | static struct factory_config factory_config; | ||
| 46 | |||
| 47 | static void read_factory_config(struct memory_accessor *a, void *context) | ||
| 48 | { | ||
| 49 | int ret; | ||
| 50 | struct davinci_soc_info *soc_info = &davinci_soc_info; | ||
| 51 | |||
| 52 | ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config)); | ||
| 53 | if (ret != sizeof(struct factory_config)) { | ||
| 54 | pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n", | ||
| 55 | ret); | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | |||
| 59 | if (factory_config.magic != FACTORY_CONFIG_MAGIC) { | ||
| 60 | pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n", | ||
| 61 | factory_config.magic); | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | |||
| 65 | if (factory_config.version != FACTORY_CONFIG_VERSION) { | ||
| 66 | pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n", | ||
| 67 | factory_config.version); | ||
| 68 | return; | ||
| 69 | } | ||
| 70 | |||
| 71 | pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac); | ||
| 72 | pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum); | ||
| 73 | if (is_valid_ether_addr(factory_config.mac)) | ||
| 74 | memcpy(soc_info->emac_pdata->mac_addr, | ||
| 75 | factory_config.mac, ETH_ALEN); | ||
| 76 | else | ||
| 77 | pr_warning("MityOMAPL138: Invalid MAC found " | ||
| 78 | "in factory config block\n"); | ||
| 79 | } | ||
| 80 | |||
| 81 | static struct at24_platform_data mityomapl138_fd_chip = { | ||
| 82 | .byte_len = 256, | ||
| 83 | .page_size = 8, | ||
| 84 | .flags = AT24_FLAG_READONLY | AT24_FLAG_IRUGO, | ||
| 85 | .setup = read_factory_config, | ||
| 86 | .context = NULL, | ||
| 87 | }; | ||
| 88 | |||
| 89 | static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { | ||
| 90 | .bus_freq = 100, /* kHz */ | ||
| 91 | .bus_delay = 0, /* usec */ | ||
| 92 | }; | ||
| 93 | |||
| 94 | /* TPS65023 voltage regulator support */ | ||
| 95 | /* 1.2V Core */ | ||
| 96 | static struct regulator_consumer_supply tps65023_dcdc1_consumers[] = { | ||
| 97 | { | ||
| 98 | .supply = "cvdd", | ||
| 99 | }, | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* 1.8V */ | ||
| 103 | static struct regulator_consumer_supply tps65023_dcdc2_consumers[] = { | ||
| 104 | { | ||
| 105 | .supply = "usb0_vdda18", | ||
| 106 | }, | ||
| 107 | { | ||
| 108 | .supply = "usb1_vdda18", | ||
| 109 | }, | ||
| 110 | { | ||
| 111 | .supply = "ddr_dvdd18", | ||
| 112 | }, | ||
| 113 | { | ||
| 114 | .supply = "sata_vddr", | ||
| 115 | }, | ||
| 116 | }; | ||
| 117 | |||
| 118 | /* 1.2V */ | ||
| 119 | static struct regulator_consumer_supply tps65023_dcdc3_consumers[] = { | ||
| 120 | { | ||
| 121 | .supply = "sata_vdd", | ||
| 122 | }, | ||
| 123 | { | ||
| 124 | .supply = "usb_cvdd", | ||
| 125 | }, | ||
| 126 | { | ||
| 127 | .supply = "pll0_vdda", | ||
| 128 | }, | ||
| 129 | { | ||
| 130 | .supply = "pll1_vdda", | ||
| 131 | }, | ||
| 132 | }; | ||
| 133 | |||
| 134 | /* 1.8V Aux LDO, not used */ | ||
| 135 | static struct regulator_consumer_supply tps65023_ldo1_consumers[] = { | ||
| 136 | { | ||
| 137 | .supply = "1.8v_aux", | ||
| 138 | }, | ||
| 139 | }; | ||
| 140 | |||
| 141 | /* FPGA VCC Aux (2.5 or 3.3) LDO */ | ||
| 142 | static struct regulator_consumer_supply tps65023_ldo2_consumers[] = { | ||
| 143 | { | ||
| 144 | .supply = "vccaux", | ||
| 145 | }, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static struct regulator_init_data tps65023_regulator_data[] = { | ||
| 149 | /* dcdc1 */ | ||
| 150 | { | ||
| 151 | .constraints = { | ||
| 152 | .min_uV = 1150000, | ||
| 153 | .max_uV = 1350000, | ||
| 154 | .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | | ||
| 155 | REGULATOR_CHANGE_STATUS, | ||
| 156 | .boot_on = 1, | ||
| 157 | }, | ||
| 158 | .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers), | ||
| 159 | .consumer_supplies = tps65023_dcdc1_consumers, | ||
| 160 | }, | ||
| 161 | /* dcdc2 */ | ||
| 162 | { | ||
| 163 | .constraints = { | ||
| 164 | .min_uV = 1800000, | ||
| 165 | .max_uV = 1800000, | ||
| 166 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
| 167 | .boot_on = 1, | ||
| 168 | }, | ||
| 169 | .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers), | ||
| 170 | .consumer_supplies = tps65023_dcdc2_consumers, | ||
| 171 | }, | ||
| 172 | /* dcdc3 */ | ||
| 173 | { | ||
| 174 | .constraints = { | ||
| 175 | .min_uV = 1200000, | ||
| 176 | .max_uV = 1200000, | ||
| 177 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
| 178 | .boot_on = 1, | ||
| 179 | }, | ||
| 180 | .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers), | ||
| 181 | .consumer_supplies = tps65023_dcdc3_consumers, | ||
| 182 | }, | ||
| 183 | /* ldo1 */ | ||
| 184 | { | ||
| 185 | .constraints = { | ||
| 186 | .min_uV = 1800000, | ||
| 187 | .max_uV = 1800000, | ||
| 188 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
| 189 | .boot_on = 1, | ||
| 190 | }, | ||
| 191 | .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers), | ||
| 192 | .consumer_supplies = tps65023_ldo1_consumers, | ||
| 193 | }, | ||
| 194 | /* ldo2 */ | ||
| 195 | { | ||
| 196 | .constraints = { | ||
| 197 | .min_uV = 2500000, | ||
| 198 | .max_uV = 3300000, | ||
| 199 | .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | | ||
| 200 | REGULATOR_CHANGE_STATUS, | ||
| 201 | .boot_on = 1, | ||
| 202 | }, | ||
| 203 | .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo2_consumers), | ||
| 204 | .consumer_supplies = tps65023_ldo2_consumers, | ||
| 205 | }, | ||
| 206 | }; | ||
| 207 | |||
| 208 | static struct i2c_board_info __initdata mityomap_tps65023_info[] = { | ||
| 209 | { | ||
| 210 | I2C_BOARD_INFO("tps65023", 0x48), | ||
| 211 | .platform_data = &tps65023_regulator_data[0], | ||
| 212 | }, | ||
| 213 | { | ||
| 214 | I2C_BOARD_INFO("24c02", 0x50), | ||
| 215 | .platform_data = &mityomapl138_fd_chip, | ||
| 216 | }, | ||
| 217 | }; | ||
| 218 | |||
| 219 | static int __init pmic_tps65023_init(void) | ||
| 220 | { | ||
| 221 | return i2c_register_board_info(1, mityomap_tps65023_info, | ||
| 222 | ARRAY_SIZE(mityomap_tps65023_info)); | ||
| 223 | } | ||
| 224 | |||
| 225 | /* | ||
| 226 | * MityDSP-L138 includes a 256 MByte large-page NAND flash | ||
| 227 | * (128K blocks). | ||
| 228 | */ | ||
| 229 | static struct mtd_partition mityomapl138_nandflash_partition[] = { | ||
| 230 | { | ||
| 231 | .name = "rootfs", | ||
| 232 | .offset = 0, | ||
| 233 | .size = SZ_128M, | ||
| 234 | .mask_flags = 0, /* MTD_WRITEABLE, */ | ||
| 235 | }, | ||
| 236 | { | ||
| 237 | .name = "homefs", | ||
| 238 | .offset = MTDPART_OFS_APPEND, | ||
| 239 | .size = MTDPART_SIZ_FULL, | ||
| 240 | .mask_flags = 0, | ||
| 241 | }, | ||
| 242 | }; | ||
| 243 | |||
| 244 | static struct davinci_nand_pdata mityomapl138_nandflash_data = { | ||
| 245 | .parts = mityomapl138_nandflash_partition, | ||
| 246 | .nr_parts = ARRAY_SIZE(mityomapl138_nandflash_partition), | ||
| 247 | .ecc_mode = NAND_ECC_HW, | ||
| 248 | .options = NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16, | ||
| 249 | .ecc_bits = 1, /* 4 bit mode is not supported with 16 bit NAND */ | ||
| 250 | }; | ||
| 251 | |||
| 252 | static struct resource mityomapl138_nandflash_resource[] = { | ||
| 253 | { | ||
| 254 | .start = DA8XX_AEMIF_CS3_BASE, | ||
| 255 | .end = DA8XX_AEMIF_CS3_BASE + SZ_512K + 2 * SZ_1K - 1, | ||
| 256 | .flags = IORESOURCE_MEM, | ||
| 257 | }, | ||
| 258 | { | ||
| 259 | .start = DA8XX_AEMIF_CTL_BASE, | ||
| 260 | .end = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1, | ||
| 261 | .flags = IORESOURCE_MEM, | ||
| 262 | }, | ||
| 263 | }; | ||
| 264 | |||
| 265 | static struct platform_device mityomapl138_nandflash_device = { | ||
| 266 | .name = "davinci_nand", | ||
| 267 | .id = 0, | ||
| 268 | .dev = { | ||
| 269 | .platform_data = &mityomapl138_nandflash_data, | ||
| 270 | }, | ||
| 271 | .num_resources = ARRAY_SIZE(mityomapl138_nandflash_resource), | ||
| 272 | .resource = mityomapl138_nandflash_resource, | ||
| 273 | }; | ||
| 274 | |||
| 275 | static struct platform_device *mityomapl138_devices[] __initdata = { | ||
| 276 | &mityomapl138_nandflash_device, | ||
| 277 | }; | ||
| 278 | |||
| 279 | static void __init mityomapl138_setup_nand(void) | ||
| 280 | { | ||
| 281 | platform_add_devices(mityomapl138_devices, | ||
| 282 | ARRAY_SIZE(mityomapl138_devices)); | ||
| 283 | } | ||
| 284 | |||
| 285 | static struct davinci_uart_config mityomapl138_uart_config __initdata = { | ||
| 286 | .enabled_uarts = 0x7, | ||
| 287 | }; | ||
| 288 | |||
| 289 | static const short mityomap_mii_pins[] = { | ||
| 290 | DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, | ||
| 291 | DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, | ||
| 292 | DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, | ||
| 293 | DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, | ||
| 294 | DA850_MDIO_D, | ||
| 295 | -1 | ||
| 296 | }; | ||
| 297 | |||
| 298 | static const short mityomap_rmii_pins[] = { | ||
| 299 | DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, | ||
| 300 | DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, | ||
| 301 | DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, | ||
| 302 | DA850_MDIO_D, | ||
| 303 | -1 | ||
| 304 | }; | ||
| 305 | |||
| 306 | static void __init mityomapl138_config_emac(void) | ||
| 307 | { | ||
| 308 | void __iomem *cfg_chip3_base; | ||
| 309 | int ret; | ||
| 310 | u32 val; | ||
| 311 | struct davinci_soc_info *soc_info = &davinci_soc_info; | ||
| 312 | |||
| 313 | soc_info->emac_pdata->rmii_en = 0; /* hardcoded for now */ | ||
| 314 | |||
| 315 | cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG); | ||
| 316 | val = __raw_readl(cfg_chip3_base); | ||
| 317 | |||
| 318 | if (soc_info->emac_pdata->rmii_en) { | ||
| 319 | val |= BIT(8); | ||
| 320 | ret = davinci_cfg_reg_list(mityomap_rmii_pins); | ||
| 321 | pr_info("RMII PHY configured\n"); | ||
| 322 | } else { | ||
| 323 | val &= ~BIT(8); | ||
| 324 | ret = davinci_cfg_reg_list(mityomap_mii_pins); | ||
| 325 | pr_info("MII PHY configured\n"); | ||
| 326 | } | ||
| 327 | |||
| 328 | if (ret) { | ||
| 329 | pr_warning("mii/rmii mux setup failed: %d\n", ret); | ||
| 330 | return; | ||
| 331 | } | ||
| 332 | |||
| 333 | /* configure the CFGCHIP3 register for RMII or MII */ | ||
| 334 | __raw_writel(val, cfg_chip3_base); | ||
| 335 | |||
| 336 | soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID; | ||
| 337 | |||
| 338 | ret = da8xx_register_emac(); | ||
| 339 | if (ret) | ||
| 340 | pr_warning("emac registration failed: %d\n", ret); | ||
| 341 | } | ||
| 342 | |||
| 343 | static struct davinci_pm_config da850_pm_pdata = { | ||
| 344 | .sleepcount = 128, | ||
| 345 | }; | ||
| 346 | |||
| 347 | static struct platform_device da850_pm_device = { | ||
| 348 | .name = "pm-davinci", | ||
| 349 | .dev = { | ||
| 350 | .platform_data = &da850_pm_pdata, | ||
| 351 | }, | ||
| 352 | .id = -1, | ||
| 353 | }; | ||
| 354 | |||
| 355 | static void __init mityomapl138_init(void) | ||
| 356 | { | ||
| 357 | int ret; | ||
| 358 | |||
| 359 | /* for now, no special EDMA channels are reserved */ | ||
| 360 | ret = da850_register_edma(NULL); | ||
| 361 | if (ret) | ||
| 362 | pr_warning("edma registration failed: %d\n", ret); | ||
| 363 | |||
| 364 | ret = da8xx_register_watchdog(); | ||
| 365 | if (ret) | ||
| 366 | pr_warning("watchdog registration failed: %d\n", ret); | ||
| 367 | |||
| 368 | davinci_serial_init(&mityomapl138_uart_config); | ||
| 369 | |||
| 370 | ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata); | ||
| 371 | if (ret) | ||
| 372 | pr_warning("i2c0 registration failed: %d\n", ret); | ||
| 373 | |||
| 374 | ret = pmic_tps65023_init(); | ||
| 375 | if (ret) | ||
| 376 | pr_warning("TPS65023 PMIC init failed: %d\n", ret); | ||
| 377 | |||
| 378 | mityomapl138_setup_nand(); | ||
| 379 | |||
| 380 | mityomapl138_config_emac(); | ||
| 381 | |||
| 382 | ret = da8xx_register_rtc(); | ||
| 383 | if (ret) | ||
| 384 | pr_warning("rtc setup failed: %d\n", ret); | ||
| 385 | |||
| 386 | ret = da850_register_cpufreq("pll0_sysclk3"); | ||
| 387 | if (ret) | ||
| 388 | pr_warning("cpufreq registration failed: %d\n", ret); | ||
| 389 | |||
| 390 | ret = da8xx_register_cpuidle(); | ||
| 391 | if (ret) | ||
| 392 | pr_warning("cpuidle registration failed: %d\n", ret); | ||
| 393 | |||
| 394 | ret = da850_register_pm(&da850_pm_device); | ||
| 395 | if (ret) | ||
| 396 | pr_warning("da850_evm_init: suspend registration failed: %d\n", | ||
| 397 | ret); | ||
| 398 | } | ||
| 399 | |||
| 400 | #ifdef CONFIG_SERIAL_8250_CONSOLE | ||
| 401 | static int __init mityomapl138_console_init(void) | ||
| 402 | { | ||
| 403 | if (!machine_is_mityomapl138()) | ||
| 404 | return 0; | ||
| 405 | |||
| 406 | return add_preferred_console("ttyS", 1, "115200"); | ||
| 407 | } | ||
| 408 | console_initcall(mityomapl138_console_init); | ||
| 409 | #endif | ||
| 410 | |||
| 411 | static void __init mityomapl138_map_io(void) | ||
| 412 | { | ||
| 413 | da850_init(); | ||
| 414 | } | ||
| 415 | |||
| 416 | MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808") | ||
| 417 | .boot_params = (DA8XX_DDR_BASE + 0x100), | ||
| 418 | .map_io = mityomapl138_map_io, | ||
| 419 | .init_irq = cp_intc_init, | ||
| 420 | .timer = &davinci_timer, | ||
| 421 | .init_machine = mityomapl138_init, | ||
| 422 | MACHINE_END | ||
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index a4def889275c..6c389ff1020e 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c | |||
| @@ -39,9 +39,7 @@ | |||
| 39 | #include <mach/mmc.h> | 39 | #include <mach/mmc.h> |
| 40 | #include <mach/usb.h> | 40 | #include <mach/usb.h> |
| 41 | 41 | ||
| 42 | #define NEUROS_OSD2_PHY_MASK 0x2 | 42 | #define NEUROS_OSD2_PHY_ID "0:01" |
| 43 | #define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ | ||
| 44 | |||
| 45 | #define LXT971_PHY_ID 0x001378e2 | 43 | #define LXT971_PHY_ID 0x001378e2 |
| 46 | #define LXT971_PHY_MASK 0xfffffff0 | 44 | #define LXT971_PHY_MASK 0xfffffff0 |
| 47 | 45 | ||
| @@ -252,8 +250,7 @@ static __init void davinci_ntosd2_init(void) | |||
| 252 | davinci_serial_init(&uart_config); | 250 | davinci_serial_init(&uart_config); |
| 253 | dm644x_init_asp(&dm644x_ntosd2_snd_data); | 251 | dm644x_init_asp(&dm644x_ntosd2_snd_data); |
| 254 | 252 | ||
| 255 | soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK; | 253 | soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID; |
| 256 | soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY; | ||
| 257 | 254 | ||
| 258 | davinci_setup_usb(1000, 8); | 255 | davinci_setup_usb(1000, 8); |
| 259 | /* | 256 | /* |
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c new file mode 100644 index 000000000000..0b8dbdb79fe0 --- /dev/null +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | /* | ||
| 2 | * Hawkboard.org based on TI's OMAP-L138 Platform | ||
| 3 | * | ||
| 4 | * Initial code: Syed Mohammed Khasim | ||
| 5 | * | ||
| 6 | * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public License | ||
| 9 | * version 2. This program is licensed "as is" without any warranty of | ||
| 10 | * any kind, whether express or implied. | ||
| 11 | */ | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/console.h> | ||
| 15 | #include <linux/gpio.h> | ||
| 16 | |||
| 17 | #include <asm/mach-types.h> | ||
| 18 | #include <asm/mach/arch.h> | ||
| 19 | |||
| 20 | #include <mach/cp_intc.h> | ||
| 21 | #include <mach/da8xx.h> | ||
| 22 | |||
| 23 | static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { | ||
| 24 | .enabled_uarts = 0x7, | ||
| 25 | }; | ||
| 26 | |||
| 27 | static __init void omapl138_hawk_init(void) | ||
| 28 | { | ||
| 29 | int ret; | ||
| 30 | |||
| 31 | davinci_serial_init(&omapl138_hawk_uart_config); | ||
| 32 | |||
| 33 | ret = da8xx_register_watchdog(); | ||
| 34 | if (ret) | ||
| 35 | pr_warning("omapl138_hawk_init: " | ||
| 36 | "watchdog registration failed: %d\n", | ||
| 37 | ret); | ||
| 38 | } | ||
| 39 | |||
| 40 | #ifdef CONFIG_SERIAL_8250_CONSOLE | ||
| 41 | static int __init omapl138_hawk_console_init(void) | ||
| 42 | { | ||
| 43 | if (!machine_is_omapl138_hawkboard()) | ||
| 44 | return 0; | ||
| 45 | |||
| 46 | return add_preferred_console("ttyS", 2, "115200"); | ||
| 47 | } | ||
| 48 | console_initcall(omapl138_hawk_console_init); | ||
| 49 | #endif | ||
| 50 | |||
| 51 | static void __init omapl138_hawk_map_io(void) | ||
| 52 | { | ||
| 53 | da850_init(); | ||
| 54 | } | ||
| 55 | |||
| 56 | MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") | ||
| 57 | .boot_params = (DA8XX_DDR_BASE + 0x100), | ||
| 58 | .map_io = omapl138_hawk_map_io, | ||
| 59 | .init_irq = cp_intc_init, | ||
| 60 | .timer = &davinci_timer, | ||
| 61 | .init_machine = omapl138_hawk_init, | ||
| 62 | MACHINE_END | ||
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 9bdf8aafcc84..61ac96d8f00d 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c | |||
| @@ -42,9 +42,7 @@ | |||
| 42 | #include <mach/mux.h> | 42 | #include <mach/mux.h> |
| 43 | #include <mach/usb.h> | 43 | #include <mach/usb.h> |
| 44 | 44 | ||
| 45 | #define SFFSDR_PHY_MASK (0x2) | 45 | #define SFFSDR_PHY_ID "0:01" |
| 46 | #define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ | ||
| 47 | |||
| 48 | static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { | 46 | static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { |
| 49 | /* U-Boot Environment: Block 0 | 47 | /* U-Boot Environment: Block 0 |
| 50 | * UBL: Block 1 | 48 | * UBL: Block 1 |
| @@ -143,8 +141,7 @@ static __init void davinci_sffsdr_init(void) | |||
| 143 | ARRAY_SIZE(davinci_sffsdr_devices)); | 141 | ARRAY_SIZE(davinci_sffsdr_devices)); |
| 144 | sffsdr_init_i2c(); | 142 | sffsdr_init_i2c(); |
| 145 | davinci_serial_init(&uart_config); | 143 | davinci_serial_init(&uart_config); |
| 146 | soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK; | 144 | soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID; |
| 147 | soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY; | ||
| 148 | davinci_setup_usb(0, 0); /* We support only peripheral mode. */ | 145 | davinci_setup_usb(0, 0); /* We support only peripheral mode. */ |
| 149 | 146 | ||
| 150 | /* mux VLYNQ pins */ | 147 | /* mux VLYNQ pins */ |
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index b4de35b78904..a6db85460227 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c | |||
| @@ -23,6 +23,9 @@ | |||
| 23 | #include <linux/ratelimit.h> | 23 | #include <linux/ratelimit.h> |
| 24 | #include <linux/mtd/mtd.h> | 24 | #include <linux/mtd/mtd.h> |
| 25 | #include <linux/mtd/partitions.h> | 25 | #include <linux/mtd/partitions.h> |
| 26 | #include <linux/input.h> | ||
| 27 | #include <linux/input/matrix_keypad.h> | ||
| 28 | |||
| 26 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
| 27 | #include <asm/mach-types.h> | 30 | #include <asm/mach-types.h> |
| 28 | 31 | ||
| @@ -141,10 +144,63 @@ static struct davinci_uart_config serial_config __initconst = { | |||
| 141 | .enabled_uarts = BIT(1), | 144 | .enabled_uarts = BIT(1), |
| 142 | }; | 145 | }; |
| 143 | 146 | ||
| 147 | static const uint32_t keymap[] = { | ||
| 148 | KEY(0, 0, KEY_NUMERIC_1), | ||
| 149 | KEY(0, 1, KEY_NUMERIC_2), | ||
| 150 | KEY(0, 2, KEY_NUMERIC_3), | ||
| 151 | KEY(0, 3, KEY_FN_F1), | ||
| 152 | KEY(0, 4, KEY_MENU), | ||
| 153 | |||
| 154 | KEY(1, 0, KEY_NUMERIC_4), | ||
| 155 | KEY(1, 1, KEY_NUMERIC_5), | ||
| 156 | KEY(1, 2, KEY_NUMERIC_6), | ||
| 157 | KEY(1, 3, KEY_UP), | ||
| 158 | KEY(1, 4, KEY_FN_F2), | ||
| 159 | |||
| 160 | KEY(2, 0, KEY_NUMERIC_7), | ||
| 161 | KEY(2, 1, KEY_NUMERIC_8), | ||
| 162 | KEY(2, 2, KEY_NUMERIC_9), | ||
| 163 | KEY(2, 3, KEY_LEFT), | ||
| 164 | KEY(2, 4, KEY_ENTER), | ||
| 165 | |||
| 166 | KEY(3, 0, KEY_NUMERIC_STAR), | ||
| 167 | KEY(3, 1, KEY_NUMERIC_0), | ||
| 168 | KEY(3, 2, KEY_NUMERIC_POUND), | ||
| 169 | KEY(3, 3, KEY_DOWN), | ||
| 170 | KEY(3, 4, KEY_RIGHT), | ||
| 171 | |||
| 172 | KEY(4, 0, KEY_FN_F3), | ||
| 173 | KEY(4, 1, KEY_FN_F4), | ||
| 174 | KEY(4, 2, KEY_MUTE), | ||
| 175 | KEY(4, 3, KEY_HOME), | ||
| 176 | KEY(4, 4, KEY_BACK), | ||
| 177 | |||
| 178 | KEY(5, 0, KEY_VOLUMEDOWN), | ||
| 179 | KEY(5, 1, KEY_VOLUMEUP), | ||
| 180 | KEY(5, 2, KEY_F1), | ||
| 181 | KEY(5, 3, KEY_F2), | ||
| 182 | KEY(5, 4, KEY_F3), | ||
| 183 | }; | ||
| 184 | |||
| 185 | static const struct matrix_keymap_data keymap_data = { | ||
| 186 | .keymap = keymap, | ||
| 187 | .keymap_size = ARRAY_SIZE(keymap), | ||
| 188 | }; | ||
| 189 | |||
| 190 | static struct matrix_keypad_platform_data keypad_config = { | ||
| 191 | .keymap_data = &keymap_data, | ||
| 192 | .num_row_gpios = 6, | ||
| 193 | .num_col_gpios = 5, | ||
| 194 | .debounce_ms = 0, /* minimum */ | ||
| 195 | .active_low = 0, /* pull up realization */ | ||
| 196 | .no_autorepeat = 0, | ||
| 197 | }; | ||
| 198 | |||
| 144 | static struct tnetv107x_device_info evm_device_info __initconst = { | 199 | static struct tnetv107x_device_info evm_device_info __initconst = { |
| 145 | .serial_config = &serial_config, | 200 | .serial_config = &serial_config, |
| 146 | .mmc_config[1] = &mmc_config, /* controller 1 */ | 201 | .mmc_config[1] = &mmc_config, /* controller 1 */ |
| 147 | .nand_config[0] = &nand_config, /* chip select 0 */ | 202 | .nand_config[0] = &nand_config, /* chip select 0 */ |
| 203 | .keypad_config = &keypad_config, | ||
| 148 | }; | 204 | }; |
| 149 | 205 | ||
| 150 | static __init void tnetv107x_evm_board_init(void) | 206 | static __init void tnetv107x_evm_board_init(void) |
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 054c303caead..01ba080433db 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c | |||
| @@ -236,7 +236,7 @@ static int __init clk_disable_unused(void) | |||
| 236 | if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc)) | 236 | if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc)) |
| 237 | continue; | 237 | continue; |
| 238 | 238 | ||
| 239 | pr_info("Clocks: disable unused %s\n", ck->name); | 239 | pr_debug("Clocks: disable unused %s\n", ck->name); |
| 240 | 240 | ||
| 241 | davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, | 241 | davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, |
| 242 | (ck->flags & PSC_SWRSTDISABLE) ? | 242 | (ck->flags & PSC_SWRSTDISABLE) ? |
| @@ -287,6 +287,79 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) | |||
| 287 | return rate; | 287 | return rate; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate) | ||
| 291 | { | ||
| 292 | unsigned v; | ||
| 293 | struct pll_data *pll; | ||
| 294 | unsigned long input; | ||
| 295 | unsigned ratio = 0; | ||
| 296 | |||
| 297 | /* If this is the PLL base clock, wrong function to call */ | ||
| 298 | if (clk->pll_data) | ||
| 299 | return -EINVAL; | ||
| 300 | |||
| 301 | /* There must be a parent... */ | ||
| 302 | if (WARN_ON(!clk->parent)) | ||
| 303 | return -EINVAL; | ||
| 304 | |||
| 305 | /* ... the parent must be a PLL... */ | ||
| 306 | if (WARN_ON(!clk->parent->pll_data)) | ||
| 307 | return -EINVAL; | ||
| 308 | |||
| 309 | /* ... and this clock must have a divider. */ | ||
| 310 | if (WARN_ON(!clk->div_reg)) | ||
| 311 | return -EINVAL; | ||
| 312 | |||
| 313 | pll = clk->parent->pll_data; | ||
| 314 | |||
| 315 | input = clk->parent->rate; | ||
| 316 | |||
| 317 | /* If pre-PLL, source clock is before the multiplier and divider(s) */ | ||
| 318 | if (clk->flags & PRE_PLL) | ||
| 319 | input = pll->input_rate; | ||
| 320 | |||
| 321 | if (input > rate) { | ||
| 322 | /* | ||
| 323 | * Can afford to provide an output little higher than requested | ||
| 324 | * only if maximum rate supported by hardware on this sysclk | ||
| 325 | * is known. | ||
| 326 | */ | ||
| 327 | if (clk->maxrate) { | ||
| 328 | ratio = DIV_ROUND_CLOSEST(input, rate); | ||
| 329 | if (input / ratio > clk->maxrate) | ||
| 330 | ratio = 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | if (ratio == 0) | ||
| 334 | ratio = DIV_ROUND_UP(input, rate); | ||
| 335 | |||
| 336 | ratio--; | ||
| 337 | } | ||
| 338 | |||
| 339 | if (ratio > PLLDIV_RATIO_MASK) | ||
| 340 | return -EINVAL; | ||
| 341 | |||
| 342 | do { | ||
| 343 | v = __raw_readl(pll->base + PLLSTAT); | ||
| 344 | } while (v & PLLSTAT_GOSTAT); | ||
| 345 | |||
| 346 | v = __raw_readl(pll->base + clk->div_reg); | ||
| 347 | v &= ~PLLDIV_RATIO_MASK; | ||
| 348 | v |= ratio | PLLDIV_EN; | ||
| 349 | __raw_writel(v, pll->base + clk->div_reg); | ||
| 350 | |||
| 351 | v = __raw_readl(pll->base + PLLCMD); | ||
| 352 | v |= PLLCMD_GOSET; | ||
| 353 | __raw_writel(v, pll->base + PLLCMD); | ||
| 354 | |||
| 355 | do { | ||
| 356 | v = __raw_readl(pll->base + PLLSTAT); | ||
| 357 | } while (v & PLLSTAT_GOSTAT); | ||
| 358 | |||
| 359 | return 0; | ||
| 360 | } | ||
| 361 | EXPORT_SYMBOL(davinci_set_sysclk_rate); | ||
| 362 | |||
| 290 | static unsigned long clk_leafclk_recalc(struct clk *clk) | 363 | static unsigned long clk_leafclk_recalc(struct clk *clk) |
| 291 | { | 364 | { |
| 292 | if (WARN_ON(!clk->parent)) | 365 | if (WARN_ON(!clk->parent)) |
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 01e36483ac3d..11099980b58b 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h | |||
| @@ -70,6 +70,9 @@ | |||
| 70 | #include <linux/list.h> | 70 | #include <linux/list.h> |
| 71 | #include <asm/clkdev.h> | 71 | #include <asm/clkdev.h> |
| 72 | 72 | ||
| 73 | #define PLLSTAT_GOSTAT BIT(0) | ||
| 74 | #define PLLCMD_GOSET BIT(0) | ||
| 75 | |||
| 73 | struct pll_data { | 76 | struct pll_data { |
| 74 | u32 phys_base; | 77 | u32 phys_base; |
| 75 | void __iomem *base; | 78 | void __iomem *base; |
| @@ -86,6 +89,7 @@ struct clk { | |||
| 86 | struct module *owner; | 89 | struct module *owner; |
| 87 | const char *name; | 90 | const char *name; |
| 88 | unsigned long rate; | 91 | unsigned long rate; |
| 92 | unsigned long maxrate; /* H/W supported max rate */ | ||
| 89 | u8 usecount; | 93 | u8 usecount; |
| 90 | u8 lpsc; | 94 | u8 lpsc; |
| 91 | u8 gpsc; | 95 | u8 gpsc; |
| @@ -118,6 +122,7 @@ struct clk { | |||
| 118 | int davinci_clk_init(struct clk_lookup *clocks); | 122 | int davinci_clk_init(struct clk_lookup *clocks); |
| 119 | int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, | 123 | int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, |
| 120 | unsigned int mult, unsigned int postdiv); | 124 | unsigned int mult, unsigned int postdiv); |
| 125 | int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate); | ||
| 121 | 126 | ||
| 122 | extern struct platform_device davinci_wdt_device; | 127 | extern struct platform_device davinci_wdt_device; |
| 123 | extern void davinci_watchdog_reset(struct platform_device *); | 128 | extern void davinci_watchdog_reset(struct platform_device *); |
diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c index d3fa6de1e20f..343de73161fa 100644 --- a/arch/arm/mach-davinci/cpufreq.c +++ b/arch/arm/mach-davinci/cpufreq.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | struct davinci_cpufreq { | 34 | struct davinci_cpufreq { |
| 35 | struct device *dev; | 35 | struct device *dev; |
| 36 | struct clk *armclk; | 36 | struct clk *armclk; |
| 37 | struct clk *asyncclk; | ||
| 38 | unsigned long asyncrate; | ||
| 37 | }; | 39 | }; |
| 38 | static struct davinci_cpufreq cpufreq; | 40 | static struct davinci_cpufreq cpufreq; |
| 39 | 41 | ||
| @@ -104,15 +106,27 @@ static int davinci_target(struct cpufreq_policy *policy, | |||
| 104 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 106 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |
| 105 | 107 | ||
| 106 | /* if moving to higher frequency, up the voltage beforehand */ | 108 | /* if moving to higher frequency, up the voltage beforehand */ |
| 107 | if (pdata->set_voltage && freqs.new > freqs.old) | 109 | if (pdata->set_voltage && freqs.new > freqs.old) { |
| 108 | pdata->set_voltage(idx); | 110 | ret = pdata->set_voltage(idx); |
| 111 | if (ret) | ||
| 112 | goto out; | ||
| 113 | } | ||
| 109 | 114 | ||
| 110 | ret = clk_set_rate(armclk, idx); | 115 | ret = clk_set_rate(armclk, idx); |
| 116 | if (ret) | ||
| 117 | goto out; | ||
| 118 | |||
| 119 | if (cpufreq.asyncclk) { | ||
| 120 | ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate); | ||
| 121 | if (ret) | ||
| 122 | goto out; | ||
| 123 | } | ||
| 111 | 124 | ||
| 112 | /* if moving to lower freq, lower the voltage after lowering freq */ | 125 | /* if moving to lower freq, lower the voltage after lowering freq */ |
| 113 | if (pdata->set_voltage && freqs.new < freqs.old) | 126 | if (pdata->set_voltage && freqs.new < freqs.old) |
| 114 | pdata->set_voltage(idx); | 127 | pdata->set_voltage(idx); |
| 115 | 128 | ||
| 129 | out: | ||
| 116 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 130 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
| 117 | 131 | ||
| 118 | return ret; | 132 | return ret; |
| @@ -185,6 +199,7 @@ static struct cpufreq_driver davinci_driver = { | |||
| 185 | static int __init davinci_cpufreq_probe(struct platform_device *pdev) | 199 | static int __init davinci_cpufreq_probe(struct platform_device *pdev) |
| 186 | { | 200 | { |
| 187 | struct davinci_cpufreq_config *pdata = pdev->dev.platform_data; | 201 | struct davinci_cpufreq_config *pdata = pdev->dev.platform_data; |
| 202 | struct clk *asyncclk; | ||
| 188 | 203 | ||
| 189 | if (!pdata) | 204 | if (!pdata) |
| 190 | return -EINVAL; | 205 | return -EINVAL; |
| @@ -199,6 +214,12 @@ static int __init davinci_cpufreq_probe(struct platform_device *pdev) | |||
| 199 | return PTR_ERR(cpufreq.armclk); | 214 | return PTR_ERR(cpufreq.armclk); |
| 200 | } | 215 | } |
| 201 | 216 | ||
| 217 | asyncclk = clk_get(cpufreq.dev, "async"); | ||
| 218 | if (!IS_ERR(asyncclk)) { | ||
| 219 | cpufreq.asyncclk = asyncclk; | ||
| 220 | cpufreq.asyncrate = clk_get_rate(asyncclk); | ||
| 221 | } | ||
| 222 | |||
| 202 | return cpufreq_register_driver(&davinci_driver); | 223 | return cpufreq_register_driver(&davinci_driver); |
| 203 | } | 224 | } |
| 204 | 225 | ||
| @@ -206,6 +227,9 @@ static int __exit davinci_cpufreq_remove(struct platform_device *pdev) | |||
| 206 | { | 227 | { |
| 207 | clk_put(cpufreq.armclk); | 228 | clk_put(cpufreq.armclk); |
| 208 | 229 | ||
| 230 | if (cpufreq.asyncclk) | ||
| 231 | clk_put(cpufreq.asyncclk); | ||
| 232 | |||
| 209 | return cpufreq_unregister_driver(&davinci_driver); | 233 | return cpufreq_unregister_driver(&davinci_driver); |
| 210 | } | 234 | } |
| 211 | 235 | ||
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 68ed58a48252..63916b902760 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c | |||
| @@ -86,6 +86,8 @@ static struct clk pll0_sysclk3 = { | |||
| 86 | .parent = &pll0_clk, | 86 | .parent = &pll0_clk, |
| 87 | .flags = CLK_PLL, | 87 | .flags = CLK_PLL, |
| 88 | .div_reg = PLLDIV3, | 88 | .div_reg = PLLDIV3, |
| 89 | .set_rate = davinci_set_sysclk_rate, | ||
| 90 | .maxrate = 100000000, | ||
| 89 | }; | 91 | }; |
| 90 | 92 | ||
| 91 | static struct clk pll0_sysclk4 = { | 93 | static struct clk pll0_sysclk4 = { |
| @@ -323,12 +325,19 @@ static struct clk lcdc_clk = { | |||
| 323 | .gpsc = 1, | 325 | .gpsc = 1, |
| 324 | }; | 326 | }; |
| 325 | 327 | ||
| 326 | static struct clk mmcsd_clk = { | 328 | static struct clk mmcsd0_clk = { |
| 327 | .name = "mmcsd", | 329 | .name = "mmcsd0", |
| 328 | .parent = &pll0_sysclk2, | 330 | .parent = &pll0_sysclk2, |
| 329 | .lpsc = DA8XX_LPSC0_MMC_SD, | 331 | .lpsc = DA8XX_LPSC0_MMC_SD, |
| 330 | }; | 332 | }; |
| 331 | 333 | ||
| 334 | static struct clk mmcsd1_clk = { | ||
| 335 | .name = "mmcsd1", | ||
| 336 | .parent = &pll0_sysclk2, | ||
| 337 | .lpsc = DA850_LPSC1_MMC_SD1, | ||
| 338 | .gpsc = 1, | ||
| 339 | }; | ||
| 340 | |||
| 332 | static struct clk aemif_clk = { | 341 | static struct clk aemif_clk = { |
| 333 | .name = "aemif", | 342 | .name = "aemif", |
| 334 | .parent = &pll0_sysclk3, | 343 | .parent = &pll0_sysclk3, |
| @@ -375,7 +384,8 @@ static struct clk_lookup da850_clks[] = { | |||
| 375 | CLK("davinci_emac.1", NULL, &emac_clk), | 384 | CLK("davinci_emac.1", NULL, &emac_clk), |
| 376 | CLK("davinci-mcasp.0", NULL, &mcasp_clk), | 385 | CLK("davinci-mcasp.0", NULL, &mcasp_clk), |
| 377 | CLK("da8xx_lcdc.0", NULL, &lcdc_clk), | 386 | CLK("da8xx_lcdc.0", NULL, &lcdc_clk), |
| 378 | CLK("davinci_mmc.0", NULL, &mmcsd_clk), | 387 | CLK("davinci_mmc.0", NULL, &mmcsd0_clk), |
| 388 | CLK("davinci_mmc.1", NULL, &mmcsd1_clk), | ||
| 379 | CLK(NULL, "aemif", &aemif_clk), | 389 | CLK(NULL, "aemif", &aemif_clk), |
| 380 | CLK(NULL, NULL, NULL), | 390 | CLK(NULL, NULL, NULL), |
| 381 | }; | 391 | }; |
| @@ -572,15 +582,9 @@ const short da850_cpgmac_pins[] __initdata = { | |||
| 572 | DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, | 582 | DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, |
| 573 | DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, | 583 | DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, |
| 574 | DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, | 584 | DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, |
| 575 | DA850_MDIO_D, | 585 | DA850_MDIO_D, DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, |
| 576 | -1 | 586 | DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, DA850_RMII_RXER, |
| 577 | }; | 587 | DA850_RMII_MHZ_50_CLK, |
| 578 | |||
| 579 | const short da850_rmii_pins[] __initdata = { | ||
| 580 | DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, | ||
| 581 | DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, | ||
| 582 | DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, | ||
| 583 | DA850_MDIO_D, | ||
| 584 | -1 | 588 | -1 |
| 585 | }; | 589 | }; |
| 586 | 590 | ||
| @@ -607,27 +611,19 @@ const short da850_mmcsd0_pins[] __initdata = { | |||
| 607 | -1 | 611 | -1 |
| 608 | }; | 612 | }; |
| 609 | 613 | ||
| 610 | const short da850_nand_pins[] __initdata = { | 614 | const short da850_emif25_pins[] __initdata = { |
| 611 | DA850_EMA_D_7, DA850_EMA_D_6, DA850_EMA_D_5, DA850_EMA_D_4, | ||
| 612 | DA850_EMA_D_3, DA850_EMA_D_2, DA850_EMA_D_1, DA850_EMA_D_0, | ||
| 613 | DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4, | ||
| 614 | DA850_NEMA_WE, DA850_NEMA_OE, | ||
| 615 | -1 | ||
| 616 | }; | ||
| 617 | |||
| 618 | const short da850_nor_pins[] __initdata = { | ||
| 619 | DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2, | 615 | DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2, |
| 620 | DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1, | 616 | DA850_NEMA_CS_3, DA850_NEMA_CS_4, DA850_NEMA_WE, DA850_NEMA_OE, |
| 621 | DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5, | 617 | DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3, |
| 622 | DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9, | 618 | DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7, |
| 623 | DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13, | 619 | DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11, |
| 624 | DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1, | 620 | DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15, |
| 625 | DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5, | 621 | DA850_EMA_A_0, DA850_EMA_A_1, DA850_EMA_A_2, DA850_EMA_A_3, |
| 626 | DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9, | 622 | DA850_EMA_A_4, DA850_EMA_A_5, DA850_EMA_A_6, DA850_EMA_A_7, |
| 627 | DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13, | 623 | DA850_EMA_A_8, DA850_EMA_A_9, DA850_EMA_A_10, DA850_EMA_A_11, |
| 628 | DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17, | 624 | DA850_EMA_A_12, DA850_EMA_A_13, DA850_EMA_A_14, DA850_EMA_A_15, |
| 629 | DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21, | 625 | DA850_EMA_A_16, DA850_EMA_A_17, DA850_EMA_A_18, DA850_EMA_A_19, |
| 630 | DA850_EMA_A_22, DA850_EMA_A_23, | 626 | DA850_EMA_A_20, DA850_EMA_A_21, DA850_EMA_A_22, DA850_EMA_A_23, |
| 631 | -1 | 627 | -1 |
| 632 | }; | 628 | }; |
| 633 | 629 | ||
| @@ -851,7 +847,7 @@ static const struct da850_opp da850_opp_300 = { | |||
| 851 | .prediv = 1, | 847 | .prediv = 1, |
| 852 | .mult = 25, | 848 | .mult = 25, |
| 853 | .postdiv = 2, | 849 | .postdiv = 2, |
| 854 | .cvdd_min = 1140000, | 850 | .cvdd_min = 1200000, |
| 855 | .cvdd_max = 1320000, | 851 | .cvdd_max = 1320000, |
| 856 | }; | 852 | }; |
| 857 | 853 | ||
| @@ -860,7 +856,7 @@ static const struct da850_opp da850_opp_200 = { | |||
| 860 | .prediv = 1, | 856 | .prediv = 1, |
| 861 | .mult = 25, | 857 | .mult = 25, |
| 862 | .postdiv = 3, | 858 | .postdiv = 3, |
| 863 | .cvdd_min = 1050000, | 859 | .cvdd_min = 1100000, |
| 864 | .cvdd_max = 1160000, | 860 | .cvdd_max = 1160000, |
| 865 | }; | 861 | }; |
| 866 | 862 | ||
| @@ -869,7 +865,7 @@ static const struct da850_opp da850_opp_96 = { | |||
| 869 | .prediv = 1, | 865 | .prediv = 1, |
| 870 | .mult = 20, | 866 | .mult = 20, |
| 871 | .postdiv = 5, | 867 | .postdiv = 5, |
| 872 | .cvdd_min = 950000, | 868 | .cvdd_min = 1000000, |
| 873 | .cvdd_max = 1050000, | 869 | .cvdd_max = 1050000, |
| 874 | }; | 870 | }; |
| 875 | 871 | ||
| @@ -929,10 +925,16 @@ static struct platform_device da850_cpufreq_device = { | |||
| 929 | .dev = { | 925 | .dev = { |
| 930 | .platform_data = &cpufreq_info, | 926 | .platform_data = &cpufreq_info, |
| 931 | }, | 927 | }, |
| 928 | .id = -1, | ||
| 932 | }; | 929 | }; |
| 933 | 930 | ||
| 934 | int __init da850_register_cpufreq(void) | 931 | int __init da850_register_cpufreq(char *async_clk) |
| 935 | { | 932 | { |
| 933 | /* cpufreq driver can help keep an "async" clock constant */ | ||
| 934 | if (async_clk) | ||
| 935 | clk_add_alias("async", da850_cpufreq_device.name, | ||
| 936 | async_clk, NULL); | ||
| 937 | |||
| 936 | return platform_device_register(&da850_cpufreq_device); | 938 | return platform_device_register(&da850_cpufreq_device); |
| 937 | } | 939 | } |
| 938 | 940 | ||
| @@ -983,7 +985,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index) | |||
| 983 | return 0; | 985 | return 0; |
| 984 | } | 986 | } |
| 985 | #else | 987 | #else |
| 986 | int __init da850_register_cpufreq(void) | 988 | int __init da850_register_cpufreq(char *async_clk) |
| 987 | { | 989 | { |
| 988 | return 0; | 990 | return 0; |
| 989 | } | 991 | } |
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 52bc7b1c6ca3..9eec63070e0c 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "clock.h" | 24 | #include "clock.h" |
| 25 | 25 | ||
| 26 | #define DA8XX_TPCC_BASE 0x01c00000 | 26 | #define DA8XX_TPCC_BASE 0x01c00000 |
| 27 | #define DA850_MMCSD1_BASE 0x01e1b000 | ||
| 27 | #define DA850_TPCC1_BASE 0x01e30000 | 28 | #define DA850_TPCC1_BASE 0x01e30000 |
| 28 | #define DA8XX_TPTC0_BASE 0x01c08000 | 29 | #define DA8XX_TPTC0_BASE 0x01c08000 |
| 29 | #define DA8XX_TPTC1_BASE 0x01c08400 | 30 | #define DA8XX_TPTC1_BASE 0x01c08400 |
| @@ -41,7 +42,6 @@ | |||
| 41 | #define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000 | 42 | #define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000 |
| 42 | #define DA8XX_EMAC_MOD_REG_OFFSET 0x2000 | 43 | #define DA8XX_EMAC_MOD_REG_OFFSET 0x2000 |
| 43 | #define DA8XX_EMAC_RAM_OFFSET 0x0000 | 44 | #define DA8XX_EMAC_RAM_OFFSET 0x0000 |
| 44 | #define DA8XX_MDIO_REG_OFFSET 0x4000 | ||
| 45 | #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K | 45 | #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K |
| 46 | 46 | ||
| 47 | void __iomem *da8xx_syscfg0_base; | 47 | void __iomem *da8xx_syscfg0_base; |
| @@ -351,7 +351,7 @@ int __init da8xx_register_watchdog(void) | |||
| 351 | static struct resource da8xx_emac_resources[] = { | 351 | static struct resource da8xx_emac_resources[] = { |
| 352 | { | 352 | { |
| 353 | .start = DA8XX_EMAC_CPPI_PORT_BASE, | 353 | .start = DA8XX_EMAC_CPPI_PORT_BASE, |
| 354 | .end = DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1, | 354 | .end = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1, |
| 355 | .flags = IORESOURCE_MEM, | 355 | .flags = IORESOURCE_MEM, |
| 356 | }, | 356 | }, |
| 357 | { | 357 | { |
| @@ -380,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = { | |||
| 380 | .ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET, | 380 | .ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET, |
| 381 | .ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET, | 381 | .ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET, |
| 382 | .ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET, | 382 | .ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET, |
| 383 | .mdio_reg_offset = DA8XX_MDIO_REG_OFFSET, | ||
| 384 | .ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE, | 383 | .ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE, |
| 385 | .version = EMAC_VERSION_2, | 384 | .version = EMAC_VERSION_2, |
| 386 | }; | 385 | }; |
| @@ -395,9 +394,34 @@ static struct platform_device da8xx_emac_device = { | |||
| 395 | .resource = da8xx_emac_resources, | 394 | .resource = da8xx_emac_resources, |
| 396 | }; | 395 | }; |
| 397 | 396 | ||
| 397 | static struct resource da8xx_mdio_resources[] = { | ||
| 398 | { | ||
| 399 | .start = DA8XX_EMAC_MDIO_BASE, | ||
| 400 | .end = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1, | ||
| 401 | .flags = IORESOURCE_MEM, | ||
| 402 | }, | ||
| 403 | }; | ||
| 404 | |||
| 405 | static struct platform_device da8xx_mdio_device = { | ||
| 406 | .name = "davinci_mdio", | ||
| 407 | .id = 0, | ||
| 408 | .num_resources = ARRAY_SIZE(da8xx_mdio_resources), | ||
| 409 | .resource = da8xx_mdio_resources, | ||
| 410 | }; | ||
| 411 | |||
| 398 | int __init da8xx_register_emac(void) | 412 | int __init da8xx_register_emac(void) |
| 399 | { | 413 | { |
| 400 | return platform_device_register(&da8xx_emac_device); | 414 | int ret; |
| 415 | |||
| 416 | ret = platform_device_register(&da8xx_mdio_device); | ||
| 417 | if (ret < 0) | ||
| 418 | return ret; | ||
| 419 | ret = platform_device_register(&da8xx_emac_device); | ||
| 420 | if (ret < 0) | ||
| 421 | return ret; | ||
| 422 | ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev), | ||
| 423 | NULL, &da8xx_emac_device.dev); | ||
| 424 | return ret; | ||
| 401 | } | 425 | } |
| 402 | 426 | ||
| 403 | static struct resource da830_mcasp1_resources[] = { | 427 | static struct resource da830_mcasp1_resources[] = { |
| @@ -566,6 +590,44 @@ int __init da8xx_register_mmcsd0(struct davinci_mmc_config *config) | |||
| 566 | return platform_device_register(&da8xx_mmcsd0_device); | 590 | return platform_device_register(&da8xx_mmcsd0_device); |
| 567 | } | 591 | } |
| 568 | 592 | ||
| 593 | #ifdef CONFIG_ARCH_DAVINCI_DA850 | ||
| 594 | static struct resource da850_mmcsd1_resources[] = { | ||
| 595 | { /* registers */ | ||
| 596 | .start = DA850_MMCSD1_BASE, | ||
| 597 | .end = DA850_MMCSD1_BASE + SZ_4K - 1, | ||
| 598 | .flags = IORESOURCE_MEM, | ||
| 599 | }, | ||
| 600 | { /* interrupt */ | ||
| 601 | .start = IRQ_DA850_MMCSDINT0_1, | ||
| 602 | .end = IRQ_DA850_MMCSDINT0_1, | ||
| 603 | .flags = IORESOURCE_IRQ, | ||
| 604 | }, | ||
| 605 | { /* DMA RX */ | ||
| 606 | .start = EDMA_CTLR_CHAN(1, 28), | ||
| 607 | .end = EDMA_CTLR_CHAN(1, 28), | ||
| 608 | .flags = IORESOURCE_DMA, | ||
| 609 | }, | ||
| 610 | { /* DMA TX */ | ||
| 611 | .start = EDMA_CTLR_CHAN(1, 29), | ||
| 612 | .end = EDMA_CTLR_CHAN(1, 29), | ||
| 613 | .flags = IORESOURCE_DMA, | ||
| 614 | }, | ||
| 615 | }; | ||
| 616 | |||
| 617 | static struct platform_device da850_mmcsd1_device = { | ||
| 618 | .name = "davinci_mmc", | ||
| 619 | .id = 1, | ||
| 620 | .num_resources = ARRAY_SIZE(da850_mmcsd1_resources), | ||
| 621 | .resource = da850_mmcsd1_resources, | ||
| 622 | }; | ||
| 623 | |||
| 624 | int __init da850_register_mmcsd1(struct davinci_mmc_config *config) | ||
| 625 | { | ||
| 626 | da850_mmcsd1_device.dev.platform_data = config; | ||
| 627 | return platform_device_register(&da850_mmcsd1_device); | ||
| 628 | } | ||
| 629 | #endif | ||
| 630 | |||
| 569 | static struct resource da8xx_rtc_resources[] = { | 631 | static struct resource da8xx_rtc_resources[] = { |
| 570 | { | 632 | { |
| 571 | .start = DA8XX_RTC_BASE, | 633 | .start = DA8XX_RTC_BASE, |
diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 2718a3a90dff..c9a86d8130d1 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c | |||
| @@ -31,8 +31,10 @@ | |||
| 31 | #define TNETV107X_TPTC0_BASE 0x01c10000 | 31 | #define TNETV107X_TPTC0_BASE 0x01c10000 |
| 32 | #define TNETV107X_TPTC1_BASE 0x01c10400 | 32 | #define TNETV107X_TPTC1_BASE 0x01c10400 |
| 33 | #define TNETV107X_WDOG_BASE 0x08086700 | 33 | #define TNETV107X_WDOG_BASE 0x08086700 |
| 34 | #define TNETV107X_TSC_BASE 0x08088500 | ||
| 34 | #define TNETV107X_SDIO0_BASE 0x08088700 | 35 | #define TNETV107X_SDIO0_BASE 0x08088700 |
| 35 | #define TNETV107X_SDIO1_BASE 0x08088800 | 36 | #define TNETV107X_SDIO1_BASE 0x08088800 |
| 37 | #define TNETV107X_KEYPAD_BASE 0x08088a00 | ||
| 36 | #define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000 | 38 | #define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000 |
| 37 | #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000 | 39 | #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000 |
| 38 | #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000 | 40 | #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000 |
| @@ -298,12 +300,55 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data) | |||
| 298 | return platform_device_register(pdev); | 300 | return platform_device_register(pdev); |
| 299 | } | 301 | } |
| 300 | 302 | ||
| 303 | static struct resource keypad_resources[] = { | ||
| 304 | { | ||
| 305 | .start = TNETV107X_KEYPAD_BASE, | ||
| 306 | .end = TNETV107X_KEYPAD_BASE + 0xff, | ||
| 307 | .flags = IORESOURCE_MEM, | ||
| 308 | }, | ||
| 309 | { | ||
| 310 | .start = IRQ_TNETV107X_KEYPAD, | ||
| 311 | .flags = IORESOURCE_IRQ, | ||
| 312 | .name = "press", | ||
| 313 | }, | ||
| 314 | { | ||
| 315 | .start = IRQ_TNETV107X_KEYPAD_FREE, | ||
| 316 | .flags = IORESOURCE_IRQ, | ||
| 317 | .name = "release", | ||
| 318 | }, | ||
| 319 | }; | ||
| 320 | |||
| 321 | static struct platform_device keypad_device = { | ||
| 322 | .name = "tnetv107x-keypad", | ||
| 323 | .num_resources = ARRAY_SIZE(keypad_resources), | ||
| 324 | .resource = keypad_resources, | ||
| 325 | }; | ||
| 326 | |||
| 327 | static struct resource tsc_resources[] = { | ||
| 328 | { | ||
| 329 | .start = TNETV107X_TSC_BASE, | ||
| 330 | .end = TNETV107X_TSC_BASE + 0xff, | ||
| 331 | .flags = IORESOURCE_MEM, | ||
| 332 | }, | ||
| 333 | { | ||
| 334 | .start = IRQ_TNETV107X_TSC, | ||
| 335 | .flags = IORESOURCE_IRQ, | ||
| 336 | }, | ||
| 337 | }; | ||
| 338 | |||
| 339 | static struct platform_device tsc_device = { | ||
| 340 | .name = "tnetv107x-ts", | ||
| 341 | .num_resources = ARRAY_SIZE(tsc_resources), | ||
| 342 | .resource = tsc_resources, | ||
| 343 | }; | ||
| 344 | |||
| 301 | void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) | 345 | void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) |
| 302 | { | 346 | { |
| 303 | int i; | 347 | int i; |
| 304 | 348 | ||
| 305 | platform_device_register(&edma_device); | 349 | platform_device_register(&edma_device); |
| 306 | platform_device_register(&tnetv107x_wdt_device); | 350 | platform_device_register(&tnetv107x_wdt_device); |
| 351 | platform_device_register(&tsc_device); | ||
| 307 | 352 | ||
| 308 | if (info->serial_config) | 353 | if (info->serial_config) |
| 309 | davinci_serial_init(info->serial_config); | 354 | davinci_serial_init(info->serial_config); |
| @@ -317,4 +362,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) | |||
| 317 | for (i = 0; i < 4; i++) | 362 | for (i = 0; i < 4; i++) |
| 318 | if (info->nand_config[i]) | 363 | if (info->nand_config[i]) |
| 319 | nand_init(i, info->nand_config[i]); | 364 | nand_init(i, info->nand_config[i]); |
| 365 | |||
| 366 | if (info->keypad_config) { | ||
| 367 | keypad_device.dev.platform_data = info->keypad_config; | ||
| 368 | platform_device_register(&keypad_device); | ||
| 369 | } | ||
| 320 | } | 370 | } |
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index de40e9c787e1..22ebc64bc9d9 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c | |||
| @@ -213,7 +213,7 @@ void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config) | |||
| 213 | IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x7c); | 213 | IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x7c); |
| 214 | 214 | ||
| 215 | /* Configure pull down control */ | 215 | /* Configure pull down control */ |
| 216 | __raw_writel((__raw_readl(pupdctl1) & ~0x400), | 216 | __raw_writel((__raw_readl(pupdctl1) & ~0xfc0), |
| 217 | pupdctl1); | 217 | pupdctl1); |
| 218 | 218 | ||
| 219 | mmcsd1_resources[0].start = DM365_MMCSD1_BASE; | 219 | mmcsd1_resources[0].start = DM365_MMCSD1_BASE; |
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 7781e35daec3..a12065e87266 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c | |||
| @@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = { | |||
| 691 | .ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET, | 691 | .ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET, |
| 692 | .ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET, | 692 | .ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET, |
| 693 | .ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET, | 693 | .ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET, |
| 694 | .mdio_reg_offset = DM365_EMAC_MDIO_OFFSET, | ||
| 695 | .ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE, | 694 | .ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE, |
| 696 | .version = EMAC_VERSION_2, | 695 | .version = EMAC_VERSION_2, |
| 697 | }; | 696 | }; |
| @@ -699,7 +698,7 @@ static struct emac_platform_data dm365_emac_pdata = { | |||
| 699 | static struct resource dm365_emac_resources[] = { | 698 | static struct resource dm365_emac_resources[] = { |
| 700 | { | 699 | { |
| 701 | .start = DM365_EMAC_BASE, | 700 | .start = DM365_EMAC_BASE, |
| 702 | .end = DM365_EMAC_BASE + 0x47ff, | 701 | .end = DM365_EMAC_BASE + SZ_16K - 1, |
| 703 | .flags = IORESOURCE_MEM, | 702 | .flags = IORESOURCE_MEM, |
| 704 | }, | 703 | }, |
| 705 | { | 704 | { |
| @@ -734,6 +733,21 @@ static struct platform_device dm365_emac_device = { | |||
| 734 | .resource = dm365_emac_resources, | 733 | .resource = dm365_emac_resources, |
| 735 | }; | 734 | }; |
| 736 | 735 | ||
| 736 | static struct resource dm365_mdio_resources[] = { | ||
| 737 | { | ||
| 738 | .start = DM365_EMAC_MDIO_BASE, | ||
| 739 | .end = DM365_EMAC_MDIO_BASE + SZ_4K - 1, | ||
| 740 | .flags = IORESOURCE_MEM, | ||
| 741 | }, | ||
| 742 | }; | ||
| 743 | |||
| 744 | static struct platform_device dm365_mdio_device = { | ||
| 745 | .name = "davinci_mdio", | ||
| 746 | .id = 0, | ||
| 747 | .num_resources = ARRAY_SIZE(dm365_mdio_resources), | ||
| 748 | .resource = dm365_mdio_resources, | ||
| 749 | }; | ||
| 750 | |||
| 737 | static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = { | 751 | static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = { |
| 738 | [IRQ_VDINT0] = 2, | 752 | [IRQ_VDINT0] = 2, |
| 739 | [IRQ_VDINT1] = 6, | 753 | [IRQ_VDINT1] = 6, |
| @@ -1219,7 +1233,12 @@ static int __init dm365_init_devices(void) | |||
| 1219 | 1233 | ||
| 1220 | davinci_cfg_reg(DM365_INT_EDMA_CC); | 1234 | davinci_cfg_reg(DM365_INT_EDMA_CC); |
| 1221 | platform_device_register(&dm365_edma_device); | 1235 | platform_device_register(&dm365_edma_device); |
| 1236 | |||
| 1237 | platform_device_register(&dm365_mdio_device); | ||
| 1222 | platform_device_register(&dm365_emac_device); | 1238 | platform_device_register(&dm365_emac_device); |
| 1239 | clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev), | ||
| 1240 | NULL, &dm365_emac_device.dev); | ||
| 1241 | |||
| 1223 | /* Add isif clock alias */ | 1242 | /* Add isif clock alias */ |
| 1224 | clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL); | 1243 | clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL); |
| 1225 | platform_device_register(&dm365_vpss_device); | 1244 | platform_device_register(&dm365_vpss_device); |
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 5e5b0a7831fb..0608dd776a16 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c | |||
| @@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = { | |||
| 322 | .ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET, | 322 | .ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET, |
| 323 | .ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET, | 323 | .ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET, |
| 324 | .ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET, | 324 | .ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET, |
| 325 | .mdio_reg_offset = DM644X_EMAC_MDIO_OFFSET, | ||
| 326 | .ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE, | 325 | .ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE, |
| 327 | .version = EMAC_VERSION_1, | 326 | .version = EMAC_VERSION_1, |
| 328 | }; | 327 | }; |
| @@ -330,7 +329,7 @@ static struct emac_platform_data dm644x_emac_pdata = { | |||
| 330 | static struct resource dm644x_emac_resources[] = { | 329 | static struct resource dm644x_emac_resources[] = { |
| 331 | { | 330 | { |
| 332 | .start = DM644X_EMAC_BASE, | 331 | .start = DM644X_EMAC_BASE, |
| 333 | .end = DM644X_EMAC_BASE + 0x47ff, | 332 | .end = DM644X_EMAC_BASE + SZ_16K - 1, |
| 334 | .flags = IORESOURCE_MEM, | 333 | .flags = IORESOURCE_MEM, |
| 335 | }, | 334 | }, |
| 336 | { | 335 | { |
| @@ -350,6 +349,21 @@ static struct platform_device dm644x_emac_device = { | |||
| 350 | .resource = dm644x_emac_resources, | 349 | .resource = dm644x_emac_resources, |
| 351 | }; | 350 | }; |
| 352 | 351 | ||
| 352 | static struct resource dm644x_mdio_resources[] = { | ||
| 353 | { | ||
| 354 | .start = DM644X_EMAC_MDIO_BASE, | ||
| 355 | .end = DM644X_EMAC_MDIO_BASE + SZ_4K - 1, | ||
| 356 | .flags = IORESOURCE_MEM, | ||
| 357 | }, | ||
| 358 | }; | ||
| 359 | |||
| 360 | static struct platform_device dm644x_mdio_device = { | ||
| 361 | .name = "davinci_mdio", | ||
| 362 | .id = 0, | ||
| 363 | .num_resources = ARRAY_SIZE(dm644x_mdio_resources), | ||
| 364 | .resource = dm644x_mdio_resources, | ||
| 365 | }; | ||
| 366 | |||
| 353 | /* | 367 | /* |
| 354 | * Device specific mux setup | 368 | * Device specific mux setup |
| 355 | * | 369 | * |
| @@ -776,7 +790,12 @@ static int __init dm644x_init_devices(void) | |||
| 776 | clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL); | 790 | clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL); |
| 777 | clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL); | 791 | clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL); |
| 778 | platform_device_register(&dm644x_edma_device); | 792 | platform_device_register(&dm644x_edma_device); |
| 793 | |||
| 794 | platform_device_register(&dm644x_mdio_device); | ||
| 779 | platform_device_register(&dm644x_emac_device); | 795 | platform_device_register(&dm644x_emac_device); |
| 796 | clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev), | ||
| 797 | NULL, &dm644x_emac_device.dev); | ||
| 798 | |||
| 780 | platform_device_register(&dm644x_vpss_device); | 799 | platform_device_register(&dm644x_vpss_device); |
| 781 | platform_device_register(&dm644x_ccdc_dev); | 800 | platform_device_register(&dm644x_ccdc_dev); |
| 782 | platform_device_register(&vpfe_capture_dev); | 801 | platform_device_register(&vpfe_capture_dev); |
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 26e8a9c7f50b..1e0f809644bb 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c | |||
| @@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = { | |||
| 358 | .ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET, | 358 | .ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET, |
| 359 | .ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET, | 359 | .ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET, |
| 360 | .ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET, | 360 | .ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET, |
| 361 | .mdio_reg_offset = DM646X_EMAC_MDIO_OFFSET, | ||
| 362 | .ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE, | 361 | .ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE, |
| 363 | .version = EMAC_VERSION_2, | 362 | .version = EMAC_VERSION_2, |
| 364 | }; | 363 | }; |
| @@ -366,7 +365,7 @@ static struct emac_platform_data dm646x_emac_pdata = { | |||
| 366 | static struct resource dm646x_emac_resources[] = { | 365 | static struct resource dm646x_emac_resources[] = { |
| 367 | { | 366 | { |
| 368 | .start = DM646X_EMAC_BASE, | 367 | .start = DM646X_EMAC_BASE, |
| 369 | .end = DM646X_EMAC_BASE + 0x47ff, | 368 | .end = DM646X_EMAC_BASE + SZ_16K - 1, |
| 370 | .flags = IORESOURCE_MEM, | 369 | .flags = IORESOURCE_MEM, |
| 371 | }, | 370 | }, |
| 372 | { | 371 | { |
| @@ -401,6 +400,21 @@ static struct platform_device dm646x_emac_device = { | |||
| 401 | .resource = dm646x_emac_resources, | 400 | .resource = dm646x_emac_resources, |
| 402 | }; | 401 | }; |
| 403 | 402 | ||
| 403 | static struct resource dm646x_mdio_resources[] = { | ||
| 404 | { | ||
| 405 | .start = DM646X_EMAC_MDIO_BASE, | ||
| 406 | .end = DM646X_EMAC_MDIO_BASE + SZ_4K - 1, | ||
| 407 | .flags = IORESOURCE_MEM, | ||
| 408 | }, | ||
| 409 | }; | ||
| 410 | |||
| 411 | static struct platform_device dm646x_mdio_device = { | ||
| 412 | .name = "davinci_mdio", | ||
| 413 | .id = 0, | ||
| 414 | .num_resources = ARRAY_SIZE(dm646x_mdio_resources), | ||
| 415 | .resource = dm646x_mdio_resources, | ||
| 416 | }; | ||
| 417 | |||
| 404 | /* | 418 | /* |
| 405 | * Device specific mux setup | 419 | * Device specific mux setup |
| 406 | * | 420 | * |
| @@ -896,7 +910,11 @@ static int __init dm646x_init_devices(void) | |||
| 896 | if (!cpu_is_davinci_dm646x()) | 910 | if (!cpu_is_davinci_dm646x()) |
| 897 | return 0; | 911 | return 0; |
| 898 | 912 | ||
| 913 | platform_device_register(&dm646x_mdio_device); | ||
| 899 | platform_device_register(&dm646x_emac_device); | 914 | platform_device_register(&dm646x_emac_device); |
| 915 | clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev), | ||
| 916 | NULL, &dm646x_emac_device.dev); | ||
| 917 | |||
| 900 | return 0; | 918 | return 0; |
| 901 | } | 919 | } |
| 902 | postcore_initcall(dm646x_init_devices); | 920 | postcore_initcall(dm646x_init_devices); |
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index 2ede598b77dd..6b9669869c46 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c | |||
| @@ -354,10 +354,12 @@ static int irq2ctlr(int irq) | |||
| 354 | static irqreturn_t dma_irq_handler(int irq, void *data) | 354 | static irqreturn_t dma_irq_handler(int irq, void *data) |
| 355 | { | 355 | { |
| 356 | int i; | 356 | int i; |
| 357 | unsigned ctlr; | 357 | int ctlr; |
| 358 | unsigned int cnt = 0; | 358 | unsigned int cnt = 0; |
| 359 | 359 | ||
| 360 | ctlr = irq2ctlr(irq); | 360 | ctlr = irq2ctlr(irq); |
| 361 | if (ctlr < 0) | ||
| 362 | return IRQ_NONE; | ||
| 361 | 363 | ||
| 362 | dev_dbg(data, "dma_irq_handler\n"); | 364 | dev_dbg(data, "dma_irq_handler\n"); |
| 363 | 365 | ||
| @@ -408,10 +410,12 @@ static irqreturn_t dma_irq_handler(int irq, void *data) | |||
| 408 | static irqreturn_t dma_ccerr_handler(int irq, void *data) | 410 | static irqreturn_t dma_ccerr_handler(int irq, void *data) |
| 409 | { | 411 | { |
| 410 | int i; | 412 | int i; |
| 411 | unsigned ctlr; | 413 | int ctlr; |
| 412 | unsigned int cnt = 0; | 414 | unsigned int cnt = 0; |
| 413 | 415 | ||
| 414 | ctlr = irq2ctlr(irq); | 416 | ctlr = irq2ctlr(irq); |
| 417 | if (ctlr < 0) | ||
| 418 | return IRQ_NONE; | ||
| 415 | 419 | ||
| 416 | dev_dbg(data, "dma_ccerr_handler\n"); | 420 | dev_dbg(data, "dma_ccerr_handler\n"); |
| 417 | 421 | ||
diff --git a/arch/arm/mach-davinci/include/mach/aemif.h b/arch/arm/mach-davinci/include/mach/aemif.h new file mode 100644 index 000000000000..05b293443097 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/aemif.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /* | ||
| 2 | * TI DaVinci AEMIF support | ||
| 3 | * | ||
| 4 | * Copyright 2010 (C) Texas Instruments, Inc. http://www.ti.com/ | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public License | ||
| 7 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 8 | * kind, whether express or implied. | ||
| 9 | */ | ||
| 10 | #ifndef _MACH_DAVINCI_AEMIF_H | ||
| 11 | #define _MACH_DAVINCI_AEMIF_H | ||
| 12 | |||
| 13 | #define NRCSR_OFFSET 0x00 | ||
| 14 | #define AWCCR_OFFSET 0x04 | ||
| 15 | #define A1CR_OFFSET 0x10 | ||
| 16 | |||
| 17 | #define ACR_ASIZE_MASK 0x3 | ||
| 18 | #define ACR_EW_MASK BIT(30) | ||
| 19 | #define ACR_SS_MASK BIT(31) | ||
| 20 | |||
| 21 | /* All timings in nanoseconds */ | ||
| 22 | struct davinci_aemif_timing { | ||
| 23 | u8 wsetup; | ||
| 24 | u8 wstrobe; | ||
| 25 | u8 whold; | ||
| 26 | |||
| 27 | u8 rsetup; | ||
| 28 | u8 rstrobe; | ||
| 29 | u8 rhold; | ||
| 30 | |||
| 31 | u8 ta; | ||
| 32 | }; | ||
| 33 | |||
| 34 | int davinci_aemif_setup_timing(struct davinci_aemif_timing *t, | ||
| 35 | void __iomem *base, unsigned cs); | ||
| 36 | #endif | ||
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 3c07059f526e..4247b3f53b33 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h | |||
| @@ -76,9 +76,10 @@ int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata); | |||
| 76 | int da8xx_register_emac(void); | 76 | int da8xx_register_emac(void); |
| 77 | int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata); | 77 | int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata); |
| 78 | int da8xx_register_mmcsd0(struct davinci_mmc_config *config); | 78 | int da8xx_register_mmcsd0(struct davinci_mmc_config *config); |
| 79 | int da850_register_mmcsd1(struct davinci_mmc_config *config); | ||
| 79 | void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata); | 80 | void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata); |
| 80 | int da8xx_register_rtc(void); | 81 | int da8xx_register_rtc(void); |
| 81 | int da850_register_cpufreq(void); | 82 | int da850_register_cpufreq(char *async_clk); |
| 82 | int da8xx_register_cpuidle(void); | 83 | int da8xx_register_cpuidle(void); |
| 83 | void __iomem * __init da8xx_get_mem_ctlr(void); | 84 | void __iomem * __init da8xx_get_mem_ctlr(void); |
| 84 | int da850_register_pm(struct platform_device *pdev); | 85 | int da850_register_pm(struct platform_device *pdev); |
| @@ -121,11 +122,9 @@ extern const short da850_uart2_pins[]; | |||
| 121 | extern const short da850_i2c0_pins[]; | 122 | extern const short da850_i2c0_pins[]; |
| 122 | extern const short da850_i2c1_pins[]; | 123 | extern const short da850_i2c1_pins[]; |
| 123 | extern const short da850_cpgmac_pins[]; | 124 | extern const short da850_cpgmac_pins[]; |
| 124 | extern const short da850_rmii_pins[]; | ||
| 125 | extern const short da850_mcasp_pins[]; | 125 | extern const short da850_mcasp_pins[]; |
| 126 | extern const short da850_lcdcntl_pins[]; | 126 | extern const short da850_lcdcntl_pins[]; |
| 127 | extern const short da850_mmcsd0_pins[]; | 127 | extern const short da850_mmcsd0_pins[]; |
| 128 | extern const short da850_nand_pins[]; | 128 | extern const short da850_emif25_pins[]; |
| 129 | extern const short da850_nor_pins[]; | ||
| 130 | 129 | ||
| 131 | #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */ | 130 | #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */ |
diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index ea5df3b49ec4..2563bf4e93a1 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h | |||
| @@ -21,10 +21,10 @@ | |||
| 21 | #include <media/davinci/vpfe_capture.h> | 21 | #include <media/davinci/vpfe_capture.h> |
| 22 | 22 | ||
| 23 | #define DM365_EMAC_BASE (0x01D07000) | 23 | #define DM365_EMAC_BASE (0x01D07000) |
| 24 | #define DM365_EMAC_MDIO_BASE (DM365_EMAC_BASE + 0x4000) | ||
| 24 | #define DM365_EMAC_CNTRL_OFFSET (0x0000) | 25 | #define DM365_EMAC_CNTRL_OFFSET (0x0000) |
| 25 | #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) | 26 | #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) |
| 26 | #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) | 27 | #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) |
| 27 | #define DM365_EMAC_MDIO_OFFSET (0x4000) | ||
| 28 | #define DM365_EMAC_CNTRL_RAM_SIZE (0x2000) | 28 | #define DM365_EMAC_CNTRL_RAM_SIZE (0x2000) |
| 29 | 29 | ||
| 30 | /* Base of key scan register bank */ | 30 | /* Base of key scan register bank */ |
diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 6fca568a0fd2..5a1b26d4e68b 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h | |||
| @@ -28,10 +28,10 @@ | |||
| 28 | #include <media/davinci/vpfe_capture.h> | 28 | #include <media/davinci/vpfe_capture.h> |
| 29 | 29 | ||
| 30 | #define DM644X_EMAC_BASE (0x01C80000) | 30 | #define DM644X_EMAC_BASE (0x01C80000) |
| 31 | #define DM644X_EMAC_MDIO_BASE (DM644X_EMAC_BASE + 0x4000) | ||
| 31 | #define DM644X_EMAC_CNTRL_OFFSET (0x0000) | 32 | #define DM644X_EMAC_CNTRL_OFFSET (0x0000) |
| 32 | #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) | 33 | #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) |
| 33 | #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) | 34 | #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) |
| 34 | #define DM644X_EMAC_MDIO_OFFSET (0x4000) | ||
| 35 | #define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) | 35 | #define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) |
| 36 | 36 | ||
| 37 | #define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000 | 37 | #define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000 |
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 0a27ee9a70e1..7a27f3f13913 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h | |||
| @@ -19,10 +19,10 @@ | |||
| 19 | #include <linux/davinci_emac.h> | 19 | #include <linux/davinci_emac.h> |
| 20 | 20 | ||
| 21 | #define DM646X_EMAC_BASE (0x01C80000) | 21 | #define DM646X_EMAC_BASE (0x01C80000) |
| 22 | #define DM646X_EMAC_MDIO_BASE (DM646X_EMAC_BASE + 0x4000) | ||
| 22 | #define DM646X_EMAC_CNTRL_OFFSET (0x0000) | 23 | #define DM646X_EMAC_CNTRL_OFFSET (0x0000) |
| 23 | #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) | 24 | #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) |
| 24 | #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) | 25 | #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) |
| 25 | #define DM646X_EMAC_MDIO_OFFSET (0x4000) | ||
| 26 | #define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000) | 26 | #define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000) |
| 27 | 27 | ||
| 28 | #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 | 28 | #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 |
diff --git a/arch/arm/mach-davinci/include/mach/nand.h b/arch/arm/mach-davinci/include/mach/nand.h index b2ad8090bd10..025151049f05 100644 --- a/arch/arm/mach-davinci/include/mach/nand.h +++ b/arch/arm/mach-davinci/include/mach/nand.h | |||
| @@ -30,9 +30,6 @@ | |||
| 30 | 30 | ||
| 31 | #include <linux/mtd/nand.h> | 31 | #include <linux/mtd/nand.h> |
| 32 | 32 | ||
| 33 | #define NRCSR_OFFSET 0x00 | ||
| 34 | #define AWCCR_OFFSET 0x04 | ||
| 35 | #define A1CR_OFFSET 0x10 | ||
| 36 | #define NANDFCR_OFFSET 0x60 | 33 | #define NANDFCR_OFFSET 0x60 |
| 37 | #define NANDFSR_OFFSET 0x64 | 34 | #define NANDFSR_OFFSET 0x64 |
| 38 | #define NANDF1ECC_OFFSET 0x70 | 35 | #define NANDF1ECC_OFFSET 0x70 |
| @@ -83,6 +80,9 @@ struct davinci_nand_pdata { /* platform_data */ | |||
| 83 | /* Main and mirror bbt descriptor overrides */ | 80 | /* Main and mirror bbt descriptor overrides */ |
| 84 | struct nand_bbt_descr *bbt_td; | 81 | struct nand_bbt_descr *bbt_td; |
| 85 | struct nand_bbt_descr *bbt_md; | 82 | struct nand_bbt_descr *bbt_md; |
| 83 | |||
| 84 | /* Access timings */ | ||
| 85 | struct davinci_aemif_timing *timing; | ||
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | #endif /* __ARCH_ARM_DAVINCI_NAND_H */ | 88 | #endif /* __ARCH_ARM_DAVINCI_NAND_H */ |
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 983da6e4554c..62b0858f68ca 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h | |||
| @@ -172,6 +172,7 @@ | |||
| 172 | #define DA8XX_LPSC1_UART2 13 | 172 | #define DA8XX_LPSC1_UART2 13 |
| 173 | #define DA8XX_LPSC1_LCDC 16 | 173 | #define DA8XX_LPSC1_LCDC 16 |
| 174 | #define DA8XX_LPSC1_PWM 17 | 174 | #define DA8XX_LPSC1_PWM 17 |
| 175 | #define DA850_LPSC1_MMC_SD1 18 | ||
| 175 | #define DA8XX_LPSC1_ECAP 20 | 176 | #define DA8XX_LPSC1_ECAP 20 |
| 176 | #define DA830_LPSC1_EQEP 21 | 177 | #define DA830_LPSC1_EQEP 21 |
| 177 | #define DA850_LPSC1_TPTC2 21 | 178 | #define DA850_LPSC1_TPTC2 21 |
diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h index c72064733123..5a681d880dcb 100644 --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #ifndef __ASSEMBLY__ | 33 | #ifndef __ASSEMBLY__ |
| 34 | 34 | ||
| 35 | #include <linux/serial_8250.h> | 35 | #include <linux/serial_8250.h> |
| 36 | #include <linux/input/matrix_keypad.h> | ||
| 37 | |||
| 36 | #include <mach/mmc.h> | 38 | #include <mach/mmc.h> |
| 37 | #include <mach/nand.h> | 39 | #include <mach/nand.h> |
| 38 | #include <mach/serial.h> | 40 | #include <mach/serial.h> |
| @@ -41,6 +43,7 @@ struct tnetv107x_device_info { | |||
| 41 | struct davinci_uart_config *serial_config; | 43 | struct davinci_uart_config *serial_config; |
| 42 | struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ | 44 | struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ |
| 43 | struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */ | 45 | struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */ |
| 46 | struct matrix_keypad_platform_data *keypad_config; | ||
| 44 | }; | 47 | }; |
| 45 | 48 | ||
| 46 | extern struct platform_device tnetv107x_wdt_device; | 49 | extern struct platform_device tnetv107x_wdt_device; |
diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192ad6eb..47723e8d75a4 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h | |||
| @@ -88,6 +88,8 @@ static inline void __arch_decomp_setup(unsigned long arch_id) | |||
| 88 | /* DA8xx boards */ | 88 | /* DA8xx boards */ |
| 89 | DEBUG_LL_DA8XX(davinci_da830_evm, 2); | 89 | DEBUG_LL_DA8XX(davinci_da830_evm, 2); |
| 90 | DEBUG_LL_DA8XX(davinci_da850_evm, 2); | 90 | DEBUG_LL_DA8XX(davinci_da850_evm, 2); |
| 91 | DEBUG_LL_DA8XX(mityomapl138, 1); | ||
| 92 | DEBUG_LL_DA8XX(omapl138_hawkboard, 2); | ||
| 91 | 93 | ||
| 92 | /* TNETV107x boards */ | 94 | /* TNETV107x boards */ |
| 93 | DEBUG_LL_TNETV107X(tnetv107x, 1); | 95 | DEBUG_LL_TNETV107X(tnetv107x, 1); |
diff --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c index 864e60482c53..daeae06430b9 100644 --- a/arch/arm/mach-davinci/tnetv107x.c +++ b/arch/arm/mach-davinci/tnetv107x.c | |||
| @@ -104,7 +104,7 @@ static u32 pll_ext_freq[] = { | |||
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | /* PSC control registers */ | 106 | /* PSC control registers */ |
| 107 | static u32 psc_regs[] __initconst = { TNETV107X_PSC_BASE }; | 107 | static u32 psc_regs[] = { TNETV107X_PSC_BASE }; |
| 108 | 108 | ||
| 109 | /* Host map for interrupt controller */ | 109 | /* Host map for interrupt controller */ |
| 110 | static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 }; | 110 | static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 }; |
| @@ -581,7 +581,14 @@ static struct davinci_id ids[] = { | |||
| 581 | .part_no = 0xb8a1, | 581 | .part_no = 0xb8a1, |
| 582 | .manufacturer = 0x017, | 582 | .manufacturer = 0x017, |
| 583 | .cpu_id = DAVINCI_CPU_ID_TNETV107X, | 583 | .cpu_id = DAVINCI_CPU_ID_TNETV107X, |
| 584 | .name = "tnetv107x rev1.0", | 584 | .name = "tnetv107x rev 1.0", |
| 585 | }, | ||
| 586 | { | ||
| 587 | .variant = 0x1, | ||
| 588 | .part_no = 0xb8a1, | ||
| 589 | .manufacturer = 0x017, | ||
| 590 | .cpu_id = DAVINCI_CPU_ID_TNETV107X, | ||
| 591 | .name = "tnetv107x rev 1.1/1.2", | ||
| 585 | }, | 592 | }, |
| 586 | }; | 593 | }; |
| 587 | 594 | ||
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index d547036aff3f..e1f8dda62799 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <linux/clk.h> | ||
| 21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 22 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
| 23 | #include <linux/i2c/pca953x.h> | 24 | #include <linux/i2c/pca953x.h> |
| @@ -38,19 +39,37 @@ | |||
| 38 | 39 | ||
| 39 | #include "mux.h" | 40 | #include "mux.h" |
| 40 | 41 | ||
| 41 | #define AM35XX_EVM_PHY_MASK (0xF) | ||
| 42 | #define AM35XX_EVM_MDIO_FREQUENCY (1000000) | 42 | #define AM35XX_EVM_MDIO_FREQUENCY (1000000) |
| 43 | 43 | ||
| 44 | static struct mdio_platform_data am3517_evm_mdio_pdata = { | ||
| 45 | .bus_freq = AM35XX_EVM_MDIO_FREQUENCY, | ||
| 46 | }; | ||
| 47 | |||
| 48 | static struct resource am3517_mdio_resources[] = { | ||
| 49 | { | ||
| 50 | .start = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, | ||
| 51 | .end = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET + | ||
| 52 | SZ_4K - 1, | ||
| 53 | .flags = IORESOURCE_MEM, | ||
| 54 | }, | ||
| 55 | }; | ||
| 56 | |||
| 57 | static struct platform_device am3517_mdio_device = { | ||
| 58 | .name = "davinci_mdio", | ||
| 59 | .id = 0, | ||
| 60 | .num_resources = ARRAY_SIZE(am3517_mdio_resources), | ||
| 61 | .resource = am3517_mdio_resources, | ||
| 62 | .dev.platform_data = &am3517_evm_mdio_pdata, | ||
| 63 | }; | ||
| 64 | |||
| 44 | static struct emac_platform_data am3517_evm_emac_pdata = { | 65 | static struct emac_platform_data am3517_evm_emac_pdata = { |
| 45 | .phy_mask = AM35XX_EVM_PHY_MASK, | ||
| 46 | .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, | ||
| 47 | .rmii_en = 1, | 66 | .rmii_en = 1, |
| 48 | }; | 67 | }; |
| 49 | 68 | ||
| 50 | static struct resource am3517_emac_resources[] = { | 69 | static struct resource am3517_emac_resources[] = { |
| 51 | { | 70 | { |
| 52 | .start = AM35XX_IPSS_EMAC_BASE, | 71 | .start = AM35XX_IPSS_EMAC_BASE, |
| 53 | .end = AM35XX_IPSS_EMAC_BASE + 0x3FFFF, | 72 | .end = AM35XX_IPSS_EMAC_BASE + 0x2FFFF, |
| 54 | .flags = IORESOURCE_MEM, | 73 | .flags = IORESOURCE_MEM, |
| 55 | }, | 74 | }, |
| 56 | { | 75 | { |
| @@ -113,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) | |||
| 113 | pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET; | 132 | pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET; |
| 114 | pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET; | 133 | pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET; |
| 115 | pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET; | 134 | pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET; |
| 116 | pdata->mdio_reg_offset = AM35XX_EMAC_MDIO_OFFSET; | ||
| 117 | pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE; | 135 | pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE; |
| 118 | pdata->version = EMAC_VERSION_2; | 136 | pdata->version = EMAC_VERSION_2; |
| 119 | pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR; | 137 | pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR; |
| @@ -121,6 +139,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) | |||
| 121 | pdata->interrupt_disable = am3517_disable_ethernet_int; | 139 | pdata->interrupt_disable = am3517_disable_ethernet_int; |
| 122 | am3517_emac_device.dev.platform_data = pdata; | 140 | am3517_emac_device.dev.platform_data = pdata; |
| 123 | platform_device_register(&am3517_emac_device); | 141 | platform_device_register(&am3517_emac_device); |
| 142 | platform_device_register(&am3517_mdio_device); | ||
| 143 | clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev), | ||
| 144 | NULL, &am3517_emac_device.dev); | ||
| 124 | 145 | ||
| 125 | regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | 146 | regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); |
| 126 | regval = regval & (~(AM35XX_CPGMACSS_SW_RST)); | 147 | regval = regval & (~(AM35XX_CPGMACSS_SW_RST)); |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 0426630f0e98..b8c51b9781db 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -443,6 +443,15 @@ config KEYBOARD_OMAP4 | |||
| 443 | To compile this driver as a module, choose M here: the | 443 | To compile this driver as a module, choose M here: the |
| 444 | module will be called omap4-keypad. | 444 | module will be called omap4-keypad. |
| 445 | 445 | ||
| 446 | config KEYBOARD_TNETV107X | ||
| 447 | tristate "TI TNETV107X keypad support" | ||
| 448 | depends on ARCH_DAVINCI_TNETV107X | ||
| 449 | help | ||
| 450 | Say Y here if you want to use the TNETV107X keypad. | ||
| 451 | |||
| 452 | To compile this driver as a module, choose M here: the | ||
| 453 | module will be called tnetv107x-keypad. | ||
| 454 | |||
| 446 | config KEYBOARD_TWL4030 | 455 | config KEYBOARD_TWL4030 |
| 447 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" | 456 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" |
| 448 | depends on TWL4030_CORE | 457 | depends on TWL4030_CORE |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index c13809c5c3a7..a34452e8ebe2 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | |||
| 40 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o | 40 | obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o |
| 41 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 41 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
| 42 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 42 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
| 43 | obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o | ||
| 43 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 44 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
| 44 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 45 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
| 45 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | 46 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o |
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c new file mode 100644 index 000000000000..b4a81ebfab92 --- /dev/null +++ b/drivers/input/keyboard/tnetv107x-keypad.c | |||
| @@ -0,0 +1,340 @@ | |||
| 1 | /* | ||
| 2 | * Texas Instruments TNETV107X Keypad Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Texas Instruments | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation version 2. | ||
| 9 | * | ||
| 10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 11 | * kind, whether express or implied; without even the implied warranty | ||
| 12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/errno.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/clk.h> | ||
| 25 | #include <linux/input/matrix_keypad.h> | ||
| 26 | |||
| 27 | #define BITS(x) (BIT(x) - 1) | ||
| 28 | |||
| 29 | #define KEYPAD_ROWS 9 | ||
| 30 | #define KEYPAD_COLS 9 | ||
| 31 | |||
| 32 | #define DEBOUNCE_MIN 0x400ul | ||
| 33 | #define DEBOUNCE_MAX 0x3ffffffful | ||
| 34 | |||
| 35 | struct keypad_regs { | ||
| 36 | u32 rev; | ||
| 37 | u32 mode; | ||
| 38 | u32 mask; | ||
| 39 | u32 pol; | ||
| 40 | u32 dclock; | ||
| 41 | u32 rclock; | ||
| 42 | u32 stable_cnt; | ||
| 43 | u32 in_en; | ||
| 44 | u32 out; | ||
| 45 | u32 out_en; | ||
| 46 | u32 in; | ||
| 47 | u32 lock; | ||
| 48 | u32 pres[3]; | ||
| 49 | }; | ||
| 50 | |||
| 51 | #define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) | ||
| 52 | #define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) | ||
| 53 | |||
| 54 | struct keypad_data { | ||
| 55 | struct input_dev *input_dev; | ||
| 56 | struct resource *res; | ||
| 57 | struct keypad_regs __iomem *regs; | ||
| 58 | struct clk *clk; | ||
| 59 | struct device *dev; | ||
| 60 | spinlock_t lock; | ||
| 61 | u32 irq_press; | ||
| 62 | u32 irq_release; | ||
| 63 | int rows, cols, row_shift; | ||
| 64 | int debounce_ms, active_low; | ||
| 65 | u32 prev_keys[3]; | ||
| 66 | unsigned short keycodes[]; | ||
| 67 | }; | ||
| 68 | |||
| 69 | static irqreturn_t keypad_irq(int irq, void *data) | ||
| 70 | { | ||
| 71 | struct keypad_data *kp = data; | ||
| 72 | int i, bit, val, row, col, code; | ||
| 73 | unsigned long flags; | ||
| 74 | u32 curr_keys[3]; | ||
| 75 | u32 change; | ||
| 76 | |||
| 77 | spin_lock_irqsave(&kp->lock, flags); | ||
| 78 | |||
| 79 | memset(curr_keys, 0, sizeof(curr_keys)); | ||
| 80 | if (irq == kp->irq_press) | ||
| 81 | for (i = 0; i < 3; i++) | ||
| 82 | curr_keys[i] = keypad_read(kp, pres[i]); | ||
| 83 | |||
| 84 | for (i = 0; i < 3; i++) { | ||
| 85 | change = curr_keys[i] ^ kp->prev_keys[i]; | ||
| 86 | |||
| 87 | while (change) { | ||
| 88 | bit = fls(change) - 1; | ||
| 89 | change ^= BIT(bit); | ||
| 90 | val = curr_keys[i] & BIT(bit); | ||
| 91 | bit += i * 32; | ||
| 92 | row = bit / KEYPAD_COLS; | ||
| 93 | col = bit % KEYPAD_COLS; | ||
| 94 | |||
| 95 | code = MATRIX_SCAN_CODE(row, col, kp->row_shift); | ||
| 96 | input_event(kp->input_dev, EV_MSC, MSC_SCAN, code); | ||
| 97 | input_report_key(kp->input_dev, kp->keycodes[code], | ||
| 98 | val); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | input_sync(kp->input_dev); | ||
| 102 | memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys)); | ||
| 103 | |||
| 104 | if (irq == kp->irq_press) | ||
| 105 | keypad_write(kp, lock, 0); /* Allow hardware updates */ | ||
| 106 | |||
| 107 | spin_unlock_irqrestore(&kp->lock, flags); | ||
| 108 | |||
| 109 | return IRQ_HANDLED; | ||
| 110 | } | ||
| 111 | |||
| 112 | static int keypad_start(struct input_dev *dev) | ||
| 113 | { | ||
| 114 | struct keypad_data *kp = input_get_drvdata(dev); | ||
| 115 | unsigned long mask, debounce, clk_rate_khz; | ||
| 116 | unsigned long flags; | ||
| 117 | |||
| 118 | clk_enable(kp->clk); | ||
| 119 | clk_rate_khz = clk_get_rate(kp->clk) / 1000; | ||
| 120 | |||
| 121 | spin_lock_irqsave(&kp->lock, flags); | ||
| 122 | |||
| 123 | /* Initialize device registers */ | ||
| 124 | keypad_write(kp, mode, 0); | ||
| 125 | |||
| 126 | mask = BITS(kp->rows) << KEYPAD_COLS; | ||
| 127 | mask |= BITS(kp->cols); | ||
| 128 | keypad_write(kp, mask, ~mask); | ||
| 129 | |||
| 130 | keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff); | ||
| 131 | keypad_write(kp, stable_cnt, 3); | ||
| 132 | |||
| 133 | debounce = kp->debounce_ms * clk_rate_khz; | ||
| 134 | debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX); | ||
| 135 | keypad_write(kp, dclock, debounce); | ||
| 136 | keypad_write(kp, rclock, 4 * debounce); | ||
| 137 | |||
| 138 | keypad_write(kp, in_en, 1); | ||
| 139 | |||
| 140 | spin_unlock_irqrestore(&kp->lock, flags); | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static void keypad_stop(struct input_dev *dev) | ||
| 146 | { | ||
| 147 | struct keypad_data *kp = input_get_drvdata(dev); | ||
| 148 | |||
| 149 | synchronize_irq(kp->irq_press); | ||
| 150 | synchronize_irq(kp->irq_release); | ||
| 151 | clk_disable(kp->clk); | ||
| 152 | } | ||
| 153 | |||
| 154 | static int __devinit keypad_probe(struct platform_device *pdev) | ||
| 155 | { | ||
| 156 | const struct matrix_keypad_platform_data *pdata; | ||
| 157 | const struct matrix_keymap_data *keymap_data; | ||
| 158 | struct device *dev = &pdev->dev; | ||
| 159 | struct keypad_data *kp; | ||
| 160 | int error = 0, sz, row_shift; | ||
| 161 | u32 rev = 0; | ||
| 162 | |||
| 163 | pdata = pdev->dev.platform_data; | ||
| 164 | if (!pdata) { | ||
| 165 | dev_err(dev, "cannot find device data\n"); | ||
| 166 | return -EINVAL; | ||
| 167 | } | ||
| 168 | |||
| 169 | keymap_data = pdata->keymap_data; | ||
| 170 | if (!keymap_data) { | ||
| 171 | dev_err(dev, "cannot find keymap data\n"); | ||
| 172 | return -EINVAL; | ||
| 173 | } | ||
| 174 | |||
| 175 | row_shift = get_count_order(pdata->num_col_gpios); | ||
| 176 | sz = offsetof(struct keypad_data, keycodes); | ||
| 177 | sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]); | ||
| 178 | kp = kzalloc(sz, GFP_KERNEL); | ||
| 179 | if (!kp) { | ||
| 180 | dev_err(dev, "cannot allocate device info\n"); | ||
| 181 | return -ENOMEM; | ||
| 182 | } | ||
| 183 | |||
| 184 | kp->dev = dev; | ||
| 185 | kp->rows = pdata->num_row_gpios; | ||
| 186 | kp->cols = pdata->num_col_gpios; | ||
| 187 | kp->row_shift = row_shift; | ||
| 188 | platform_set_drvdata(pdev, kp); | ||
| 189 | spin_lock_init(&kp->lock); | ||
| 190 | |||
| 191 | kp->irq_press = platform_get_irq_byname(pdev, "press"); | ||
| 192 | kp->irq_release = platform_get_irq_byname(pdev, "release"); | ||
| 193 | if (kp->irq_press < 0 || kp->irq_release < 0) { | ||
| 194 | dev_err(dev, "cannot determine device interrupts\n"); | ||
| 195 | error = -ENODEV; | ||
| 196 | goto error_res; | ||
| 197 | } | ||
| 198 | |||
| 199 | kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 200 | if (!kp->res) { | ||
| 201 | dev_err(dev, "cannot determine register area\n"); | ||
| 202 | error = -ENODEV; | ||
| 203 | goto error_res; | ||
| 204 | } | ||
| 205 | |||
| 206 | if (!request_mem_region(kp->res->start, resource_size(kp->res), | ||
| 207 | pdev->name)) { | ||
| 208 | dev_err(dev, "cannot claim register memory\n"); | ||
| 209 | kp->res = NULL; | ||
| 210 | error = -EINVAL; | ||
| 211 | goto error_res; | ||
| 212 | } | ||
| 213 | |||
| 214 | kp->regs = ioremap(kp->res->start, resource_size(kp->res)); | ||
| 215 | if (!kp->regs) { | ||
| 216 | dev_err(dev, "cannot map register memory\n"); | ||
| 217 | error = -ENOMEM; | ||
| 218 | goto error_map; | ||
| 219 | } | ||
| 220 | |||
| 221 | kp->clk = clk_get(dev, NULL); | ||
| 222 | if (!kp->clk) { | ||
| 223 | dev_err(dev, "cannot claim device clock\n"); | ||
| 224 | error = -EINVAL; | ||
| 225 | goto error_clk; | ||
| 226 | } | ||
| 227 | |||
| 228 | error = request_threaded_irq(kp->irq_press, NULL, keypad_irq, 0, | ||
| 229 | dev_name(dev), kp); | ||
| 230 | if (error < 0) { | ||
| 231 | dev_err(kp->dev, "Could not allocate keypad press key irq\n"); | ||
| 232 | goto error_irq_press; | ||
| 233 | } | ||
| 234 | |||
| 235 | error = request_threaded_irq(kp->irq_release, NULL, keypad_irq, 0, | ||
| 236 | dev_name(dev), kp); | ||
| 237 | if (error < 0) { | ||
| 238 | dev_err(kp->dev, "Could not allocate keypad release key irq\n"); | ||
| 239 | goto error_irq_release; | ||
| 240 | } | ||
| 241 | |||
| 242 | kp->input_dev = input_allocate_device(); | ||
| 243 | if (!kp->input_dev) { | ||
| 244 | dev_err(dev, "cannot allocate input device\n"); | ||
| 245 | error = -ENOMEM; | ||
| 246 | goto error_input; | ||
| 247 | } | ||
| 248 | input_set_drvdata(kp->input_dev, kp); | ||
| 249 | |||
| 250 | kp->input_dev->name = pdev->name; | ||
| 251 | kp->input_dev->dev.parent = &pdev->dev; | ||
| 252 | kp->input_dev->open = keypad_start; | ||
| 253 | kp->input_dev->close = keypad_stop; | ||
| 254 | kp->input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
| 255 | if (!pdata->no_autorepeat) | ||
| 256 | kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
| 257 | |||
| 258 | clk_enable(kp->clk); | ||
| 259 | rev = keypad_read(kp, rev); | ||
| 260 | kp->input_dev->id.bustype = BUS_HOST; | ||
| 261 | kp->input_dev->id.product = ((rev >> 8) & 0x07); | ||
| 262 | kp->input_dev->id.version = ((rev >> 16) & 0xfff); | ||
| 263 | clk_disable(kp->clk); | ||
| 264 | |||
| 265 | kp->input_dev->keycode = kp->keycodes; | ||
| 266 | kp->input_dev->keycodesize = sizeof(kp->keycodes[0]); | ||
| 267 | kp->input_dev->keycodemax = kp->rows << kp->row_shift; | ||
| 268 | |||
| 269 | matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes, | ||
| 270 | kp->input_dev->keybit); | ||
| 271 | |||
| 272 | input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); | ||
| 273 | |||
| 274 | error = input_register_device(kp->input_dev); | ||
| 275 | if (error < 0) { | ||
| 276 | dev_err(dev, "Could not register input device\n"); | ||
| 277 | goto error_reg; | ||
| 278 | } | ||
| 279 | |||
| 280 | return 0; | ||
| 281 | |||
| 282 | |||
| 283 | error_reg: | ||
| 284 | input_free_device(kp->input_dev); | ||
| 285 | error_input: | ||
| 286 | free_irq(kp->irq_release, kp); | ||
| 287 | error_irq_release: | ||
| 288 | free_irq(kp->irq_press, kp); | ||
| 289 | error_irq_press: | ||
| 290 | clk_put(kp->clk); | ||
| 291 | error_clk: | ||
| 292 | iounmap(kp->regs); | ||
| 293 | error_map: | ||
| 294 | release_mem_region(kp->res->start, resource_size(kp->res)); | ||
| 295 | error_res: | ||
| 296 | platform_set_drvdata(pdev, NULL); | ||
| 297 | kfree(kp); | ||
| 298 | return error; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int __devexit keypad_remove(struct platform_device *pdev) | ||
| 302 | { | ||
| 303 | struct keypad_data *kp = platform_get_drvdata(pdev); | ||
| 304 | |||
| 305 | free_irq(kp->irq_press, kp); | ||
| 306 | free_irq(kp->irq_release, kp); | ||
| 307 | input_unregister_device(kp->input_dev); | ||
| 308 | clk_put(kp->clk); | ||
| 309 | iounmap(kp->regs); | ||
| 310 | release_mem_region(kp->res->start, resource_size(kp->res)); | ||
| 311 | platform_set_drvdata(pdev, NULL); | ||
| 312 | kfree(kp); | ||
| 313 | |||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static struct platform_driver keypad_driver = { | ||
| 318 | .probe = keypad_probe, | ||
| 319 | .remove = __devexit_p(keypad_remove), | ||
| 320 | .driver.name = "tnetv107x-keypad", | ||
| 321 | .driver.owner = THIS_MODULE, | ||
| 322 | }; | ||
| 323 | |||
| 324 | static int __init keypad_init(void) | ||
| 325 | { | ||
| 326 | return platform_driver_register(&keypad_driver); | ||
| 327 | } | ||
| 328 | |||
| 329 | static void __exit keypad_exit(void) | ||
| 330 | { | ||
| 331 | platform_driver_unregister(&keypad_driver); | ||
| 332 | } | ||
| 333 | |||
| 334 | module_init(keypad_init); | ||
| 335 | module_exit(keypad_exit); | ||
| 336 | |||
| 337 | MODULE_AUTHOR("Cyril Chemparathy"); | ||
| 338 | MODULE_DESCRIPTION("TNETV107X Keypad Driver"); | ||
| 339 | MODULE_ALIAS("platform: tnetv107x-keypad"); | ||
| 340 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0ea361f23fa7..06ea8da95c62 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -362,6 +362,15 @@ config TOUCHSCREEN_MIGOR | |||
| 362 | To compile this driver as a module, choose M here: the | 362 | To compile this driver as a module, choose M here: the |
| 363 | module will be called migor_ts. | 363 | module will be called migor_ts. |
| 364 | 364 | ||
| 365 | config TOUCHSCREEN_TNETV107X | ||
| 366 | tristate "TI TNETV107X touchscreen support" | ||
| 367 | depends on ARCH_DAVINCI_TNETV107X | ||
| 368 | help | ||
| 369 | Say Y here if you want to use the TNETV107X touchscreen. | ||
| 370 | |||
| 371 | To compile this driver as a module, choose M here: the | ||
| 372 | module will be called tnetv107x-ts. | ||
| 373 | |||
| 365 | config TOUCHSCREEN_TOUCHRIGHT | 374 | config TOUCHSCREEN_TOUCHRIGHT |
| 366 | tristate "Touchright serial touchscreen" | 375 | tristate "Touchright serial touchscreen" |
| 367 | select SERIO | 376 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 99b353c4e9ae..7cc1b4f4b677 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | |||
| 40 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o | 40 | obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o |
| 41 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 41 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
| 42 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 42 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
| 43 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | ||
| 43 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 44 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
| 44 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 45 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
| 45 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 46 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c new file mode 100644 index 000000000000..cf1dba2e267c --- /dev/null +++ b/drivers/input/touchscreen/tnetv107x-ts.c | |||
| @@ -0,0 +1,396 @@ | |||
| 1 | /* | ||
| 2 | * Texas Instruments TNETV107X Touchscreen Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Texas Instruments | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation version 2. | ||
| 9 | * | ||
| 10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 11 | * kind, whether express or implied; without even the implied warranty | ||
| 12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/errno.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/ctype.h> | ||
| 24 | #include <linux/io.h> | ||
| 25 | #include <linux/clk.h> | ||
| 26 | |||
| 27 | #include <mach/tnetv107x.h> | ||
| 28 | |||
| 29 | #define TSC_PENUP_POLL (HZ / 5) | ||
| 30 | #define IDLE_TIMEOUT 100 /* msec */ | ||
| 31 | |||
| 32 | /* | ||
| 33 | * The first and last samples of a touch interval are usually garbage and need | ||
| 34 | * to be filtered out with these devices. The following definitions control | ||
| 35 | * the number of samples skipped. | ||
| 36 | */ | ||
| 37 | #define TSC_HEAD_SKIP 1 | ||
| 38 | #define TSC_TAIL_SKIP 1 | ||
| 39 | #define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) | ||
| 40 | #define TSC_SAMPLES (TSC_SKIP + 1) | ||
| 41 | |||
| 42 | /* Register Offsets */ | ||
| 43 | struct tsc_regs { | ||
| 44 | u32 rev; | ||
| 45 | u32 tscm; | ||
| 46 | u32 bwcm; | ||
| 47 | u32 swc; | ||
| 48 | u32 adcchnl; | ||
| 49 | u32 adcdata; | ||
| 50 | u32 chval[4]; | ||
| 51 | }; | ||
| 52 | |||
| 53 | /* TSC Mode Configuration Register (tscm) bits */ | ||
| 54 | #define WMODE BIT(0) | ||
| 55 | #define TSKIND BIT(1) | ||
| 56 | #define ZMEASURE_EN BIT(2) | ||
| 57 | #define IDLE BIT(3) | ||
| 58 | #define TSC_EN BIT(4) | ||
| 59 | #define STOP BIT(5) | ||
| 60 | #define ONE_SHOT BIT(6) | ||
| 61 | #define SINGLE BIT(7) | ||
| 62 | #define AVG BIT(8) | ||
| 63 | #define AVGNUM(x) (((x) & 0x03) << 9) | ||
| 64 | #define PVSTC(x) (((x) & 0x07) << 11) | ||
| 65 | #define PON BIT(14) | ||
| 66 | #define PONBG BIT(15) | ||
| 67 | #define AFERST BIT(16) | ||
| 68 | |||
| 69 | /* ADC DATA Capture Register bits */ | ||
| 70 | #define DATA_VALID BIT(16) | ||
| 71 | |||
| 72 | /* Register Access Macros */ | ||
| 73 | #define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) | ||
| 74 | #define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); | ||
| 75 | #define tsc_set_bits(ts, reg, val) \ | ||
| 76 | tsc_write(ts, reg, tsc_read(ts, reg) | (val)) | ||
| 77 | #define tsc_clr_bits(ts, reg, val) \ | ||
| 78 | tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) | ||
| 79 | |||
| 80 | struct sample { | ||
| 81 | int x, y, p; | ||
| 82 | }; | ||
| 83 | |||
| 84 | struct tsc_data { | ||
| 85 | struct input_dev *input_dev; | ||
| 86 | struct resource *res; | ||
| 87 | struct tsc_regs __iomem *regs; | ||
| 88 | struct timer_list timer; | ||
| 89 | spinlock_t lock; | ||
| 90 | struct clk *clk; | ||
| 91 | struct device *dev; | ||
| 92 | int sample_count; | ||
| 93 | struct sample samples[TSC_SAMPLES]; | ||
| 94 | int tsc_irq; | ||
| 95 | }; | ||
| 96 | |||
| 97 | static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) | ||
| 98 | { | ||
| 99 | int x, y, z1, z2, t, p = 0; | ||
| 100 | u32 val; | ||
| 101 | |||
| 102 | val = tsc_read(ts, chval[0]); | ||
| 103 | if (val & DATA_VALID) | ||
| 104 | x = val & 0xffff; | ||
| 105 | else | ||
| 106 | return -EINVAL; | ||
| 107 | |||
| 108 | y = tsc_read(ts, chval[1]) & 0xffff; | ||
| 109 | z1 = tsc_read(ts, chval[2]) & 0xffff; | ||
| 110 | z2 = tsc_read(ts, chval[3]) & 0xffff; | ||
| 111 | |||
| 112 | if (z1) { | ||
| 113 | t = ((600 * x) * (z2 - z1)); | ||
| 114 | p = t / (u32) (z1 << 12); | ||
| 115 | if (p < 0) | ||
| 116 | p = 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | sample->x = x; | ||
| 120 | sample->y = y; | ||
| 121 | sample->p = p; | ||
| 122 | |||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static void tsc_poll(unsigned long data) | ||
| 127 | { | ||
| 128 | struct tsc_data *ts = (struct tsc_data *)data; | ||
| 129 | unsigned long flags; | ||
| 130 | int i, val, x, y, p; | ||
| 131 | |||
| 132 | spin_lock_irqsave(&ts->lock, flags); | ||
| 133 | |||
| 134 | if (ts->sample_count >= TSC_SKIP) { | ||
| 135 | input_report_abs(ts->input_dev, ABS_PRESSURE, 0); | ||
| 136 | input_report_key(ts->input_dev, BTN_TOUCH, 0); | ||
| 137 | input_sync(ts->input_dev); | ||
| 138 | } else if (ts->sample_count > 0) { | ||
| 139 | /* | ||
| 140 | * A touch event lasted less than our skip count. Salvage and | ||
| 141 | * report anyway. | ||
| 142 | */ | ||
| 143 | for (i = 0, val = 0; i < ts->sample_count; i++) | ||
| 144 | val += ts->samples[i].x; | ||
| 145 | x = val / ts->sample_count; | ||
| 146 | |||
| 147 | for (i = 0, val = 0; i < ts->sample_count; i++) | ||
| 148 | val += ts->samples[i].y; | ||
| 149 | y = val / ts->sample_count; | ||
| 150 | |||
| 151 | for (i = 0, val = 0; i < ts->sample_count; i++) | ||
| 152 | val += ts->samples[i].p; | ||
| 153 | p = val / ts->sample_count; | ||
| 154 | |||
| 155 | input_report_abs(ts->input_dev, ABS_X, x); | ||
| 156 | input_report_abs(ts->input_dev, ABS_Y, y); | ||
| 157 | input_report_abs(ts->input_dev, ABS_PRESSURE, p); | ||
| 158 | input_report_key(ts->input_dev, BTN_TOUCH, 1); | ||
| 159 | input_sync(ts->input_dev); | ||
| 160 | } | ||
| 161 | |||
| 162 | ts->sample_count = 0; | ||
| 163 | |||
| 164 | spin_unlock_irqrestore(&ts->lock, flags); | ||
| 165 | } | ||
| 166 | |||
| 167 | static irqreturn_t tsc_irq(int irq, void *dev_id) | ||
| 168 | { | ||
| 169 | struct tsc_data *ts = (struct tsc_data *)dev_id; | ||
| 170 | struct sample *sample; | ||
| 171 | int index; | ||
| 172 | |||
| 173 | spin_lock(&ts->lock); | ||
| 174 | |||
| 175 | index = ts->sample_count % TSC_SAMPLES; | ||
| 176 | sample = &ts->samples[index]; | ||
| 177 | if (tsc_read_sample(ts, sample) < 0) | ||
| 178 | goto out; | ||
| 179 | |||
| 180 | if (++ts->sample_count >= TSC_SKIP) { | ||
| 181 | index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; | ||
| 182 | sample = &ts->samples[index]; | ||
| 183 | |||
| 184 | input_report_abs(ts->input_dev, ABS_X, sample->x); | ||
| 185 | input_report_abs(ts->input_dev, ABS_Y, sample->y); | ||
| 186 | input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); | ||
| 187 | if (ts->sample_count == TSC_SKIP) | ||
| 188 | input_report_key(ts->input_dev, BTN_TOUCH, 1); | ||
| 189 | input_sync(ts->input_dev); | ||
| 190 | } | ||
| 191 | mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); | ||
| 192 | out: | ||
| 193 | spin_unlock(&ts->lock); | ||
| 194 | return IRQ_HANDLED; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int tsc_start(struct input_dev *dev) | ||
| 198 | { | ||
| 199 | struct tsc_data *ts = input_get_drvdata(dev); | ||
| 200 | unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); | ||
| 201 | u32 val; | ||
| 202 | |||
| 203 | clk_enable(ts->clk); | ||
| 204 | |||
| 205 | /* Go to idle mode, before any initialization */ | ||
| 206 | while (time_after(timeout, jiffies)) { | ||
| 207 | if (tsc_read(ts, tscm) & IDLE) | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | |||
| 211 | if (time_before(timeout, jiffies)) { | ||
| 212 | dev_warn(ts->dev, "timeout waiting for idle\n"); | ||
| 213 | clk_disable(ts->clk); | ||
| 214 | return -EIO; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* Configure TSC Control register*/ | ||
| 218 | val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); | ||
| 219 | tsc_write(ts, tscm, val); | ||
| 220 | |||
| 221 | /* Bring TSC out of reset: Clear AFE reset bit */ | ||
| 222 | val &= ~(AFERST); | ||
| 223 | tsc_write(ts, tscm, val); | ||
| 224 | |||
| 225 | /* Configure all pins for hardware control*/ | ||
| 226 | tsc_write(ts, bwcm, 0); | ||
| 227 | |||
| 228 | /* Finally enable the TSC */ | ||
| 229 | tsc_set_bits(ts, tscm, TSC_EN); | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | static void tsc_stop(struct input_dev *dev) | ||
| 235 | { | ||
| 236 | struct tsc_data *ts = input_get_drvdata(dev); | ||
| 237 | |||
| 238 | tsc_clr_bits(ts, tscm, TSC_EN); | ||
| 239 | synchronize_irq(ts->tsc_irq); | ||
| 240 | del_timer_sync(&ts->timer); | ||
| 241 | clk_disable(ts->clk); | ||
| 242 | } | ||
| 243 | |||
| 244 | static int __devinit tsc_probe(struct platform_device *pdev) | ||
| 245 | { | ||
| 246 | struct device *dev = &pdev->dev; | ||
| 247 | struct tsc_data *ts; | ||
| 248 | int error = 0; | ||
| 249 | u32 rev = 0; | ||
| 250 | |||
| 251 | ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); | ||
| 252 | if (!ts) { | ||
| 253 | dev_err(dev, "cannot allocate device info\n"); | ||
| 254 | return -ENOMEM; | ||
| 255 | } | ||
| 256 | |||
| 257 | ts->dev = dev; | ||
| 258 | spin_lock_init(&ts->lock); | ||
| 259 | setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); | ||
| 260 | platform_set_drvdata(pdev, ts); | ||
| 261 | |||
| 262 | ts->tsc_irq = platform_get_irq(pdev, 0); | ||
| 263 | if (ts->tsc_irq < 0) { | ||
| 264 | dev_err(dev, "cannot determine device interrupt\n"); | ||
| 265 | error = -ENODEV; | ||
| 266 | goto error_res; | ||
| 267 | } | ||
| 268 | |||
| 269 | ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 270 | if (!ts->res) { | ||
| 271 | dev_err(dev, "cannot determine register area\n"); | ||
| 272 | error = -ENODEV; | ||
| 273 | goto error_res; | ||
| 274 | } | ||
| 275 | |||
| 276 | if (!request_mem_region(ts->res->start, resource_size(ts->res), | ||
| 277 | pdev->name)) { | ||
| 278 | dev_err(dev, "cannot claim register memory\n"); | ||
| 279 | ts->res = NULL; | ||
| 280 | error = -EINVAL; | ||
| 281 | goto error_res; | ||
| 282 | } | ||
| 283 | |||
| 284 | ts->regs = ioremap(ts->res->start, resource_size(ts->res)); | ||
| 285 | if (!ts->regs) { | ||
| 286 | dev_err(dev, "cannot map register memory\n"); | ||
| 287 | error = -ENOMEM; | ||
| 288 | goto error_map; | ||
| 289 | } | ||
| 290 | |||
| 291 | ts->clk = clk_get(dev, NULL); | ||
| 292 | if (!ts->clk) { | ||
| 293 | dev_err(dev, "cannot claim device clock\n"); | ||
| 294 | error = -EINVAL; | ||
| 295 | goto error_clk; | ||
| 296 | } | ||
| 297 | |||
| 298 | error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, 0, | ||
| 299 | dev_name(dev), ts); | ||
| 300 | if (error < 0) { | ||
| 301 | dev_err(ts->dev, "Could not allocate ts irq\n"); | ||
| 302 | goto error_irq; | ||
| 303 | } | ||
| 304 | |||
| 305 | ts->input_dev = input_allocate_device(); | ||
| 306 | if (!ts->input_dev) { | ||
| 307 | dev_err(dev, "cannot allocate input device\n"); | ||
| 308 | error = -ENOMEM; | ||
| 309 | goto error_input; | ||
| 310 | } | ||
| 311 | input_set_drvdata(ts->input_dev, ts); | ||
| 312 | |||
| 313 | ts->input_dev->name = pdev->name; | ||
| 314 | ts->input_dev->id.bustype = BUS_HOST; | ||
| 315 | ts->input_dev->dev.parent = &pdev->dev; | ||
| 316 | ts->input_dev->open = tsc_start; | ||
| 317 | ts->input_dev->close = tsc_stop; | ||
| 318 | |||
| 319 | clk_enable(ts->clk); | ||
| 320 | rev = tsc_read(ts, rev); | ||
| 321 | ts->input_dev->id.product = ((rev >> 8) & 0x07); | ||
| 322 | ts->input_dev->id.version = ((rev >> 16) & 0xfff); | ||
| 323 | clk_disable(ts->clk); | ||
| 324 | |||
| 325 | __set_bit(EV_KEY, ts->input_dev->evbit); | ||
| 326 | __set_bit(EV_ABS, ts->input_dev->evbit); | ||
| 327 | __set_bit(BTN_TOUCH, ts->input_dev->keybit); | ||
| 328 | |||
| 329 | input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); | ||
| 330 | input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); | ||
| 331 | input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); | ||
| 332 | |||
| 333 | error = input_register_device(ts->input_dev); | ||
| 334 | if (error < 0) { | ||
| 335 | dev_err(dev, "failed input device registration\n"); | ||
| 336 | goto error_reg; | ||
| 337 | } | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | |||
| 341 | error_reg: | ||
| 342 | input_free_device(ts->input_dev); | ||
| 343 | error_input: | ||
| 344 | free_irq(ts->tsc_irq, ts); | ||
| 345 | error_irq: | ||
| 346 | clk_put(ts->clk); | ||
| 347 | error_clk: | ||
| 348 | iounmap(ts->regs); | ||
| 349 | error_map: | ||
| 350 | release_mem_region(ts->res->start, resource_size(ts->res)); | ||
| 351 | error_res: | ||
| 352 | platform_set_drvdata(pdev, NULL); | ||
| 353 | kfree(ts); | ||
| 354 | |||
| 355 | return error; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int __devexit tsc_remove(struct platform_device *pdev) | ||
| 359 | { | ||
| 360 | struct tsc_data *ts = platform_get_drvdata(pdev); | ||
| 361 | |||
| 362 | input_unregister_device(ts->input_dev); | ||
| 363 | free_irq(ts->tsc_irq, ts); | ||
| 364 | clk_put(ts->clk); | ||
| 365 | iounmap(ts->regs); | ||
| 366 | release_mem_region(ts->res->start, resource_size(ts->res)); | ||
| 367 | platform_set_drvdata(pdev, NULL); | ||
| 368 | kfree(ts); | ||
| 369 | |||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | static struct platform_driver tsc_driver = { | ||
| 374 | .probe = tsc_probe, | ||
| 375 | .remove = __devexit_p(tsc_remove), | ||
| 376 | .driver.name = "tnetv107x-ts", | ||
| 377 | .driver.owner = THIS_MODULE, | ||
| 378 | }; | ||
| 379 | |||
| 380 | static int __init tsc_init(void) | ||
| 381 | { | ||
| 382 | return platform_driver_register(&tsc_driver); | ||
| 383 | } | ||
| 384 | |||
| 385 | static void __exit tsc_exit(void) | ||
| 386 | { | ||
| 387 | platform_driver_unregister(&tsc_driver); | ||
| 388 | } | ||
| 389 | |||
| 390 | module_init(tsc_init); | ||
| 391 | module_exit(tsc_exit); | ||
| 392 | |||
| 393 | MODULE_AUTHOR("Cyril Chemparathy"); | ||
| 394 | MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); | ||
| 395 | MODULE_ALIAS("platform: tnetv107x-ts"); | ||
| 396 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 2ac7367afe77..8beb0d0233b5 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 36 | 36 | ||
| 37 | #include <mach/nand.h> | 37 | #include <mach/nand.h> |
| 38 | #include <mach/aemif.h> | ||
| 38 | 39 | ||
| 39 | #include <asm/mach-types.h> | 40 | #include <asm/mach-types.h> |
| 40 | 41 | ||
| @@ -74,6 +75,8 @@ struct davinci_nand_info { | |||
| 74 | uint32_t mask_cle; | 75 | uint32_t mask_cle; |
| 75 | 76 | ||
| 76 | uint32_t core_chipsel; | 77 | uint32_t core_chipsel; |
| 78 | |||
| 79 | struct davinci_aemif_timing *timing; | ||
| 77 | }; | 80 | }; |
| 78 | 81 | ||
| 79 | static DEFINE_SPINLOCK(davinci_nand_lock); | 82 | static DEFINE_SPINLOCK(davinci_nand_lock); |
| @@ -478,36 +481,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd) | |||
| 478 | return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0); | 481 | return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0); |
| 479 | } | 482 | } |
| 480 | 483 | ||
| 481 | static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info) | ||
| 482 | { | ||
| 483 | uint32_t regval, a1cr; | ||
| 484 | |||
| 485 | /* | ||
| 486 | * NAND FLASH timings @ PLL1 == 459 MHz | ||
| 487 | * - AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz | ||
| 488 | * - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns | ||
| 489 | */ | ||
| 490 | regval = 0 | ||
| 491 | | (0 << 31) /* selectStrobe */ | ||
| 492 | | (0 << 30) /* extWait (never with NAND) */ | ||
| 493 | | (1 << 26) /* writeSetup 10 ns */ | ||
| 494 | | (3 << 20) /* writeStrobe 40 ns */ | ||
| 495 | | (1 << 17) /* writeHold 10 ns */ | ||
| 496 | | (0 << 13) /* readSetup 10 ns */ | ||
| 497 | | (3 << 7) /* readStrobe 60 ns */ | ||
| 498 | | (0 << 4) /* readHold 10 ns */ | ||
| 499 | | (3 << 2) /* turnAround ?? ns */ | ||
| 500 | | (0 << 0) /* asyncSize 8-bit bus */ | ||
| 501 | ; | ||
| 502 | a1cr = davinci_nand_readl(info, A1CR_OFFSET); | ||
| 503 | if (a1cr != regval) { | ||
| 504 | dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \ | ||
| 505 | "reg to 0x%08x, was 0x%08x, should be done by " \ | ||
| 506 | "bootloader.\n", regval, a1cr); | ||
| 507 | davinci_nand_writel(info, A1CR_OFFSET, regval); | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 511 | /*----------------------------------------------------------------------*/ | 484 | /*----------------------------------------------------------------------*/ |
| 512 | 485 | ||
| 513 | /* An ECC layout for using 4-bit ECC with small-page flash, storing | 486 | /* An ECC layout for using 4-bit ECC with small-page flash, storing |
| @@ -611,6 +584,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
| 611 | info->chip.options = pdata->options; | 584 | info->chip.options = pdata->options; |
| 612 | info->chip.bbt_td = pdata->bbt_td; | 585 | info->chip.bbt_td = pdata->bbt_td; |
| 613 | info->chip.bbt_md = pdata->bbt_md; | 586 | info->chip.bbt_md = pdata->bbt_md; |
| 587 | info->timing = pdata->timing; | ||
| 614 | 588 | ||
| 615 | info->ioaddr = (uint32_t __force) vaddr; | 589 | info->ioaddr = (uint32_t __force) vaddr; |
| 616 | 590 | ||
| @@ -688,15 +662,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
| 688 | goto err_clk_enable; | 662 | goto err_clk_enable; |
| 689 | } | 663 | } |
| 690 | 664 | ||
| 691 | /* EMIF timings should normally be set by the boot loader, | 665 | /* |
| 692 | * especially after boot-from-NAND. The *only* reason to | 666 | * Setup Async configuration register in case we did not boot from |
| 693 | * have this special casing for the DM6446 EVM is to work | 667 | * NAND and so bootloader did not bother to set it up. |
| 694 | * with boot-from-NOR ... with CS0 manually re-jumpered | ||
| 695 | * (after startup) so it addresses the NAND flash, not NOR. | ||
| 696 | * Even for dev boards, that's unusually rude... | ||
| 697 | */ | 668 | */ |
| 698 | if (machine_is_davinci_evm()) | 669 | val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4); |
| 699 | nand_dm6446evm_flash_init(info); | 670 | |
| 671 | /* Extended Wait is not valid and Select Strobe mode is not used */ | ||
| 672 | val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK); | ||
| 673 | if (info->chip.options & NAND_BUSWIDTH_16) | ||
| 674 | val |= 0x1; | ||
| 675 | |||
| 676 | davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val); | ||
| 677 | |||
| 678 | ret = davinci_aemif_setup_timing(info->timing, info->base, | ||
| 679 | info->core_chipsel); | ||
| 680 | if (ret < 0) { | ||
| 681 | dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); | ||
| 682 | goto err_timing; | ||
| 683 | } | ||
| 700 | 684 | ||
| 701 | spin_lock_irq(&davinci_nand_lock); | 685 | spin_lock_irq(&davinci_nand_lock); |
| 702 | 686 | ||
| @@ -809,6 +793,7 @@ syndrome_done: | |||
| 809 | return 0; | 793 | return 0; |
| 810 | 794 | ||
| 811 | err_scan: | 795 | err_scan: |
| 796 | err_timing: | ||
| 812 | clk_disable(info->clk); | 797 | clk_disable(info->clk); |
| 813 | 798 | ||
| 814 | err_clk_enable: | 799 | err_clk_enable: |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 77c1fab7d774..702f598f4953 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -954,6 +954,8 @@ config NET_NETX | |||
| 954 | config TI_DAVINCI_EMAC | 954 | config TI_DAVINCI_EMAC |
| 955 | tristate "TI DaVinci EMAC Support" | 955 | tristate "TI DaVinci EMAC Support" |
| 956 | depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) | 956 | depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) |
| 957 | select TI_DAVINCI_MDIO | ||
| 958 | select TI_DAVINCI_CPDMA | ||
| 957 | select PHYLIB | 959 | select PHYLIB |
| 958 | help | 960 | help |
| 959 | This driver supports TI's DaVinci Ethernet . | 961 | This driver supports TI's DaVinci Ethernet . |
| @@ -961,6 +963,25 @@ config TI_DAVINCI_EMAC | |||
| 961 | To compile this driver as a module, choose M here: the module | 963 | To compile this driver as a module, choose M here: the module |
| 962 | will be called davinci_emac_driver. This is recommended. | 964 | will be called davinci_emac_driver. This is recommended. |
| 963 | 965 | ||
| 966 | config TI_DAVINCI_MDIO | ||
| 967 | tristate "TI DaVinci MDIO Support" | ||
| 968 | depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) | ||
| 969 | select PHYLIB | ||
| 970 | help | ||
| 971 | This driver supports TI's DaVinci MDIO module. | ||
| 972 | |||
| 973 | To compile this driver as a module, choose M here: the module | ||
| 974 | will be called davinci_mdio. This is recommended. | ||
| 975 | |||
| 976 | config TI_DAVINCI_CPDMA | ||
| 977 | tristate "TI DaVinci CPDMA Support" | ||
| 978 | depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) | ||
| 979 | help | ||
| 980 | This driver supports TI's DaVinci CPDMA dma engine. | ||
| 981 | |||
| 982 | To compile this driver as a module, choose M here: the module | ||
| 983 | will be called davinci_cpdma. This is recommended. | ||
| 984 | |||
| 964 | config DM9000 | 985 | config DM9000 |
| 965 | tristate "DM9000 support" | 986 | tristate "DM9000 support" |
| 966 | depends on ARM || BLACKFIN || MIPS | 987 | depends on ARM || BLACKFIN || MIPS |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b8bf93d4a132..652fc6b98039 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
| @@ -7,6 +7,8 @@ obj-$(CONFIG_MDIO) += mdio.o | |||
| 7 | obj-$(CONFIG_PHYLIB) += phy/ | 7 | obj-$(CONFIG_PHYLIB) += phy/ |
| 8 | 8 | ||
| 9 | obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o | 9 | obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o |
| 10 | obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o | ||
| 11 | obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o | ||
| 10 | 12 | ||
| 11 | obj-$(CONFIG_E1000) += e1000/ | 13 | obj-$(CONFIG_E1000) += e1000/ |
| 12 | obj-$(CONFIG_E1000E) += e1000e/ | 14 | obj-$(CONFIG_E1000E) += e1000e/ |
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c new file mode 100644 index 000000000000..e92b2b6cd8c4 --- /dev/null +++ b/drivers/net/davinci_cpdma.c | |||
| @@ -0,0 +1,965 @@ | |||
| 1 | /* | ||
| 2 | * Texas Instruments CPDMA Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Texas Instruments | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation version 2. | ||
| 9 | * | ||
| 10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 11 | * kind, whether express or implied; without even the implied warranty | ||
| 12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/spinlock.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/err.h> | ||
| 20 | #include <linux/dma-mapping.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | |||
| 23 | #include "davinci_cpdma.h" | ||
| 24 | |||
| 25 | /* DMA Registers */ | ||
| 26 | #define CPDMA_TXIDVER 0x00 | ||
| 27 | #define CPDMA_TXCONTROL 0x04 | ||
| 28 | #define CPDMA_TXTEARDOWN 0x08 | ||
| 29 | #define CPDMA_RXIDVER 0x10 | ||
| 30 | #define CPDMA_RXCONTROL 0x14 | ||
| 31 | #define CPDMA_SOFTRESET 0x1c | ||
| 32 | #define CPDMA_RXTEARDOWN 0x18 | ||
| 33 | #define CPDMA_TXINTSTATRAW 0x80 | ||
| 34 | #define CPDMA_TXINTSTATMASKED 0x84 | ||
| 35 | #define CPDMA_TXINTMASKSET 0x88 | ||
| 36 | #define CPDMA_TXINTMASKCLEAR 0x8c | ||
| 37 | #define CPDMA_MACINVECTOR 0x90 | ||
| 38 | #define CPDMA_MACEOIVECTOR 0x94 | ||
| 39 | #define CPDMA_RXINTSTATRAW 0xa0 | ||
| 40 | #define CPDMA_RXINTSTATMASKED 0xa4 | ||
| 41 | #define CPDMA_RXINTMASKSET 0xa8 | ||
| 42 | #define CPDMA_RXINTMASKCLEAR 0xac | ||
| 43 | #define CPDMA_DMAINTSTATRAW 0xb0 | ||
| 44 | #define CPDMA_DMAINTSTATMASKED 0xb4 | ||
| 45 | #define CPDMA_DMAINTMASKSET 0xb8 | ||
| 46 | #define CPDMA_DMAINTMASKCLEAR 0xbc | ||
| 47 | #define CPDMA_DMAINT_HOSTERR BIT(1) | ||
| 48 | |||
| 49 | /* the following exist only if has_ext_regs is set */ | ||
| 50 | #define CPDMA_DMACONTROL 0x20 | ||
| 51 | #define CPDMA_DMASTATUS 0x24 | ||
| 52 | #define CPDMA_RXBUFFOFS 0x28 | ||
| 53 | #define CPDMA_EM_CONTROL 0x2c | ||
| 54 | |||
| 55 | /* Descriptor mode bits */ | ||
| 56 | #define CPDMA_DESC_SOP BIT(31) | ||
| 57 | #define CPDMA_DESC_EOP BIT(30) | ||
| 58 | #define CPDMA_DESC_OWNER BIT(29) | ||
| 59 | #define CPDMA_DESC_EOQ BIT(28) | ||
| 60 | #define CPDMA_DESC_TD_COMPLETE BIT(27) | ||
| 61 | #define CPDMA_DESC_PASS_CRC BIT(26) | ||
| 62 | |||
| 63 | #define CPDMA_TEARDOWN_VALUE 0xfffffffc | ||
| 64 | |||
| 65 | struct cpdma_desc { | ||
| 66 | /* hardware fields */ | ||
| 67 | u32 hw_next; | ||
| 68 | u32 hw_buffer; | ||
| 69 | u32 hw_len; | ||
| 70 | u32 hw_mode; | ||
| 71 | /* software fields */ | ||
| 72 | void *sw_token; | ||
| 73 | u32 sw_buffer; | ||
| 74 | u32 sw_len; | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct cpdma_desc_pool { | ||
| 78 | u32 phys; | ||
| 79 | void __iomem *iomap; /* ioremap map */ | ||
| 80 | void *cpumap; /* dma_alloc map */ | ||
| 81 | int desc_size, mem_size; | ||
| 82 | int num_desc, used_desc; | ||
| 83 | unsigned long *bitmap; | ||
| 84 | struct device *dev; | ||
| 85 | spinlock_t lock; | ||
| 86 | }; | ||
| 87 | |||
| 88 | enum cpdma_state { | ||
| 89 | CPDMA_STATE_IDLE, | ||
| 90 | CPDMA_STATE_ACTIVE, | ||
| 91 | CPDMA_STATE_TEARDOWN, | ||
| 92 | }; | ||
| 93 | |||
| 94 | const char *cpdma_state_str[] = { "idle", "active", "teardown" }; | ||
| 95 | |||
| 96 | struct cpdma_ctlr { | ||
| 97 | enum cpdma_state state; | ||
| 98 | struct cpdma_params params; | ||
| 99 | struct device *dev; | ||
| 100 | struct cpdma_desc_pool *pool; | ||
| 101 | spinlock_t lock; | ||
| 102 | struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS]; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct cpdma_chan { | ||
| 106 | enum cpdma_state state; | ||
| 107 | struct cpdma_ctlr *ctlr; | ||
| 108 | int chan_num; | ||
| 109 | spinlock_t lock; | ||
| 110 | struct cpdma_desc __iomem *head, *tail; | ||
| 111 | int count; | ||
| 112 | void __iomem *hdp, *cp, *rxfree; | ||
| 113 | u32 mask; | ||
| 114 | cpdma_handler_fn handler; | ||
| 115 | enum dma_data_direction dir; | ||
| 116 | struct cpdma_chan_stats stats; | ||
| 117 | /* offsets into dmaregs */ | ||
| 118 | int int_set, int_clear, td; | ||
| 119 | }; | ||
| 120 | |||
| 121 | /* The following make access to common cpdma_ctlr params more readable */ | ||
| 122 | #define dmaregs params.dmaregs | ||
| 123 | #define num_chan params.num_chan | ||
| 124 | |||
| 125 | /* various accessors */ | ||
| 126 | #define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs)) | ||
| 127 | #define chan_read(chan, fld) __raw_readl((chan)->fld) | ||
| 128 | #define desc_read(desc, fld) __raw_readl(&(desc)->fld) | ||
| 129 | #define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs)) | ||
| 130 | #define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld) | ||
| 131 | #define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld) | ||
| 132 | |||
| 133 | /* | ||
| 134 | * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci | ||
| 135 | * emac) have dedicated on-chip memory for these descriptors. Some other | ||
| 136 | * devices (e.g. cpsw switches) use plain old memory. Descriptor pools | ||
| 137 | * abstract out these details | ||
| 138 | */ | ||
| 139 | static struct cpdma_desc_pool * | ||
| 140 | cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align) | ||
| 141 | { | ||
| 142 | int bitmap_size; | ||
| 143 | struct cpdma_desc_pool *pool; | ||
| 144 | |||
| 145 | pool = kzalloc(sizeof(*pool), GFP_KERNEL); | ||
| 146 | if (!pool) | ||
| 147 | return NULL; | ||
| 148 | |||
| 149 | spin_lock_init(&pool->lock); | ||
| 150 | |||
| 151 | pool->dev = dev; | ||
| 152 | pool->mem_size = size; | ||
| 153 | pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align); | ||
| 154 | pool->num_desc = size / pool->desc_size; | ||
| 155 | |||
| 156 | bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long); | ||
| 157 | pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL); | ||
| 158 | if (!pool->bitmap) | ||
| 159 | goto fail; | ||
| 160 | |||
| 161 | if (phys) { | ||
| 162 | pool->phys = phys; | ||
| 163 | pool->iomap = ioremap(phys, size); | ||
| 164 | } else { | ||
| 165 | pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, | ||
| 166 | GFP_KERNEL); | ||
| 167 | pool->iomap = (void __force __iomem *)pool->cpumap; | ||
| 168 | } | ||
| 169 | |||
| 170 | if (pool->iomap) | ||
| 171 | return pool; | ||
| 172 | |||
| 173 | fail: | ||
| 174 | kfree(pool->bitmap); | ||
| 175 | kfree(pool); | ||
| 176 | return NULL; | ||
| 177 | } | ||
| 178 | |||
| 179 | static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool) | ||
| 180 | { | ||
| 181 | unsigned long flags; | ||
| 182 | |||
| 183 | if (!pool) | ||
| 184 | return; | ||
| 185 | |||
| 186 | spin_lock_irqsave(&pool->lock, flags); | ||
| 187 | WARN_ON(pool->used_desc); | ||
| 188 | kfree(pool->bitmap); | ||
| 189 | if (pool->cpumap) { | ||
| 190 | dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap, | ||
| 191 | pool->phys); | ||
| 192 | } else { | ||
| 193 | iounmap(pool->iomap); | ||
| 194 | } | ||
| 195 | spin_unlock_irqrestore(&pool->lock, flags); | ||
| 196 | kfree(pool); | ||
| 197 | } | ||
| 198 | |||
| 199 | static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, | ||
| 200 | struct cpdma_desc __iomem *desc) | ||
| 201 | { | ||
| 202 | if (!desc) | ||
| 203 | return 0; | ||
| 204 | return pool->phys + (__force dma_addr_t)desc - | ||
| 205 | (__force dma_addr_t)pool->iomap; | ||
| 206 | } | ||
| 207 | |||
| 208 | static inline struct cpdma_desc __iomem * | ||
| 209 | desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma) | ||
| 210 | { | ||
| 211 | return dma ? pool->iomap + dma - pool->phys : NULL; | ||
| 212 | } | ||
| 213 | |||
| 214 | static struct cpdma_desc __iomem * | ||
| 215 | cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) | ||
| 216 | { | ||
| 217 | unsigned long flags; | ||
| 218 | int index; | ||
| 219 | struct cpdma_desc __iomem *desc = NULL; | ||
| 220 | |||
| 221 | spin_lock_irqsave(&pool->lock, flags); | ||
| 222 | |||
| 223 | index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, | ||
| 224 | num_desc, 0); | ||
| 225 | if (index < pool->num_desc) { | ||
| 226 | bitmap_set(pool->bitmap, index, num_desc); | ||
| 227 | desc = pool->iomap + pool->desc_size * index; | ||
| 228 | pool->used_desc++; | ||
| 229 | } | ||
| 230 | |||
| 231 | spin_unlock_irqrestore(&pool->lock, flags); | ||
| 232 | return desc; | ||
| 233 | } | ||
| 234 | |||
| 235 | static void cpdma_desc_free(struct cpdma_desc_pool *pool, | ||
| 236 | struct cpdma_desc __iomem *desc, int num_desc) | ||
| 237 | { | ||
| 238 | unsigned long flags, index; | ||
| 239 | |||
| 240 | index = ((unsigned long)desc - (unsigned long)pool->iomap) / | ||
| 241 | pool->desc_size; | ||
| 242 | spin_lock_irqsave(&pool->lock, flags); | ||
| 243 | bitmap_clear(pool->bitmap, index, num_desc); | ||
| 244 | pool->used_desc--; | ||
| 245 | spin_unlock_irqrestore(&pool->lock, flags); | ||
| 246 | } | ||
| 247 | |||
| 248 | struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) | ||
| 249 | { | ||
| 250 | struct cpdma_ctlr *ctlr; | ||
| 251 | |||
| 252 | ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL); | ||
| 253 | if (!ctlr) | ||
| 254 | return NULL; | ||
| 255 | |||
| 256 | ctlr->state = CPDMA_STATE_IDLE; | ||
| 257 | ctlr->params = *params; | ||
| 258 | ctlr->dev = params->dev; | ||
| 259 | spin_lock_init(&ctlr->lock); | ||
| 260 | |||
| 261 | ctlr->pool = cpdma_desc_pool_create(ctlr->dev, | ||
| 262 | ctlr->params.desc_mem_phys, | ||
| 263 | ctlr->params.desc_mem_size, | ||
| 264 | ctlr->params.desc_align); | ||
| 265 | if (!ctlr->pool) { | ||
| 266 | kfree(ctlr); | ||
| 267 | return NULL; | ||
| 268 | } | ||
| 269 | |||
| 270 | if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS)) | ||
| 271 | ctlr->num_chan = CPDMA_MAX_CHANNELS; | ||
| 272 | return ctlr; | ||
| 273 | } | ||
| 274 | |||
| 275 | int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) | ||
| 276 | { | ||
| 277 | unsigned long flags; | ||
| 278 | int i; | ||
| 279 | |||
| 280 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 281 | if (ctlr->state != CPDMA_STATE_IDLE) { | ||
| 282 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 283 | return -EBUSY; | ||
| 284 | } | ||
| 285 | |||
| 286 | if (ctlr->params.has_soft_reset) { | ||
| 287 | unsigned long timeout = jiffies + HZ/10; | ||
| 288 | |||
| 289 | dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); | ||
| 290 | while (time_before(jiffies, timeout)) { | ||
| 291 | if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | WARN_ON(!time_before(jiffies, timeout)); | ||
| 295 | } | ||
| 296 | |||
| 297 | for (i = 0; i < ctlr->num_chan; i++) { | ||
| 298 | __raw_writel(0, ctlr->params.txhdp + 4 * i); | ||
| 299 | __raw_writel(0, ctlr->params.rxhdp + 4 * i); | ||
| 300 | __raw_writel(0, ctlr->params.txcp + 4 * i); | ||
| 301 | __raw_writel(0, ctlr->params.rxcp + 4 * i); | ||
| 302 | } | ||
| 303 | |||
| 304 | dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); | ||
| 305 | dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); | ||
| 306 | |||
| 307 | dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); | ||
| 308 | dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); | ||
| 309 | |||
| 310 | ctlr->state = CPDMA_STATE_ACTIVE; | ||
| 311 | |||
| 312 | for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { | ||
| 313 | if (ctlr->channels[i]) | ||
| 314 | cpdma_chan_start(ctlr->channels[i]); | ||
| 315 | } | ||
| 316 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) | ||
| 321 | { | ||
| 322 | unsigned long flags; | ||
| 323 | int i; | ||
| 324 | |||
| 325 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 326 | if (ctlr->state != CPDMA_STATE_ACTIVE) { | ||
| 327 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 328 | return -EINVAL; | ||
| 329 | } | ||
| 330 | |||
| 331 | ctlr->state = CPDMA_STATE_TEARDOWN; | ||
| 332 | |||
| 333 | for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { | ||
| 334 | if (ctlr->channels[i]) | ||
| 335 | cpdma_chan_stop(ctlr->channels[i]); | ||
| 336 | } | ||
| 337 | |||
| 338 | dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); | ||
| 339 | dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); | ||
| 340 | |||
| 341 | dma_reg_write(ctlr, CPDMA_TXCONTROL, 0); | ||
| 342 | dma_reg_write(ctlr, CPDMA_RXCONTROL, 0); | ||
| 343 | |||
| 344 | ctlr->state = CPDMA_STATE_IDLE; | ||
| 345 | |||
| 346 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | |||
| 350 | int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr) | ||
| 351 | { | ||
| 352 | struct device *dev = ctlr->dev; | ||
| 353 | unsigned long flags; | ||
| 354 | int i; | ||
| 355 | |||
| 356 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 357 | |||
| 358 | dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]); | ||
| 359 | |||
| 360 | dev_info(dev, "CPDMA: txidver: %x", | ||
| 361 | dma_reg_read(ctlr, CPDMA_TXIDVER)); | ||
| 362 | dev_info(dev, "CPDMA: txcontrol: %x", | ||
| 363 | dma_reg_read(ctlr, CPDMA_TXCONTROL)); | ||
| 364 | dev_info(dev, "CPDMA: txteardown: %x", | ||
| 365 | dma_reg_read(ctlr, CPDMA_TXTEARDOWN)); | ||
| 366 | dev_info(dev, "CPDMA: rxidver: %x", | ||
| 367 | dma_reg_read(ctlr, CPDMA_RXIDVER)); | ||
| 368 | dev_info(dev, "CPDMA: rxcontrol: %x", | ||
| 369 | dma_reg_read(ctlr, CPDMA_RXCONTROL)); | ||
| 370 | dev_info(dev, "CPDMA: softreset: %x", | ||
| 371 | dma_reg_read(ctlr, CPDMA_SOFTRESET)); | ||
| 372 | dev_info(dev, "CPDMA: rxteardown: %x", | ||
| 373 | dma_reg_read(ctlr, CPDMA_RXTEARDOWN)); | ||
| 374 | dev_info(dev, "CPDMA: txintstatraw: %x", | ||
| 375 | dma_reg_read(ctlr, CPDMA_TXINTSTATRAW)); | ||
| 376 | dev_info(dev, "CPDMA: txintstatmasked: %x", | ||
| 377 | dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED)); | ||
| 378 | dev_info(dev, "CPDMA: txintmaskset: %x", | ||
| 379 | dma_reg_read(ctlr, CPDMA_TXINTMASKSET)); | ||
| 380 | dev_info(dev, "CPDMA: txintmaskclear: %x", | ||
| 381 | dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR)); | ||
| 382 | dev_info(dev, "CPDMA: macinvector: %x", | ||
| 383 | dma_reg_read(ctlr, CPDMA_MACINVECTOR)); | ||
| 384 | dev_info(dev, "CPDMA: maceoivector: %x", | ||
| 385 | dma_reg_read(ctlr, CPDMA_MACEOIVECTOR)); | ||
| 386 | dev_info(dev, "CPDMA: rxintstatraw: %x", | ||
| 387 | dma_reg_read(ctlr, CPDMA_RXINTSTATRAW)); | ||
| 388 | dev_info(dev, "CPDMA: rxintstatmasked: %x", | ||
| 389 | dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED)); | ||
| 390 | dev_info(dev, "CPDMA: rxintmaskset: %x", | ||
| 391 | dma_reg_read(ctlr, CPDMA_RXINTMASKSET)); | ||
| 392 | dev_info(dev, "CPDMA: rxintmaskclear: %x", | ||
| 393 | dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR)); | ||
| 394 | dev_info(dev, "CPDMA: dmaintstatraw: %x", | ||
| 395 | dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW)); | ||
| 396 | dev_info(dev, "CPDMA: dmaintstatmasked: %x", | ||
| 397 | dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED)); | ||
| 398 | dev_info(dev, "CPDMA: dmaintmaskset: %x", | ||
| 399 | dma_reg_read(ctlr, CPDMA_DMAINTMASKSET)); | ||
| 400 | dev_info(dev, "CPDMA: dmaintmaskclear: %x", | ||
| 401 | dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR)); | ||
| 402 | |||
| 403 | if (!ctlr->params.has_ext_regs) { | ||
| 404 | dev_info(dev, "CPDMA: dmacontrol: %x", | ||
| 405 | dma_reg_read(ctlr, CPDMA_DMACONTROL)); | ||
| 406 | dev_info(dev, "CPDMA: dmastatus: %x", | ||
| 407 | dma_reg_read(ctlr, CPDMA_DMASTATUS)); | ||
| 408 | dev_info(dev, "CPDMA: rxbuffofs: %x", | ||
| 409 | dma_reg_read(ctlr, CPDMA_RXBUFFOFS)); | ||
| 410 | } | ||
| 411 | |||
| 412 | for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) | ||
| 413 | if (ctlr->channels[i]) | ||
| 414 | cpdma_chan_dump(ctlr->channels[i]); | ||
| 415 | |||
| 416 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 417 | return 0; | ||
| 418 | } | ||
| 419 | |||
| 420 | int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) | ||
| 421 | { | ||
| 422 | unsigned long flags; | ||
| 423 | int ret = 0, i; | ||
| 424 | |||
| 425 | if (!ctlr) | ||
| 426 | return -EINVAL; | ||
| 427 | |||
| 428 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 429 | if (ctlr->state != CPDMA_STATE_IDLE) | ||
| 430 | cpdma_ctlr_stop(ctlr); | ||
| 431 | |||
| 432 | for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { | ||
| 433 | if (ctlr->channels[i]) | ||
| 434 | cpdma_chan_destroy(ctlr->channels[i]); | ||
| 435 | } | ||
| 436 | |||
| 437 | cpdma_desc_pool_destroy(ctlr->pool); | ||
| 438 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 439 | kfree(ctlr); | ||
| 440 | return ret; | ||
| 441 | } | ||
| 442 | |||
| 443 | int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) | ||
| 444 | { | ||
| 445 | unsigned long flags; | ||
| 446 | int i, reg; | ||
| 447 | |||
| 448 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 449 | if (ctlr->state != CPDMA_STATE_ACTIVE) { | ||
| 450 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 451 | return -EINVAL; | ||
| 452 | } | ||
| 453 | |||
| 454 | reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR; | ||
| 455 | dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR); | ||
| 456 | |||
| 457 | for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { | ||
| 458 | if (ctlr->channels[i]) | ||
| 459 | cpdma_chan_int_ctrl(ctlr->channels[i], enable); | ||
| 460 | } | ||
| 461 | |||
| 462 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 463 | return 0; | ||
| 464 | } | ||
| 465 | |||
| 466 | void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) | ||
| 467 | { | ||
| 468 | dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); | ||
| 469 | } | ||
| 470 | |||
| 471 | struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, | ||
| 472 | cpdma_handler_fn handler) | ||
| 473 | { | ||
| 474 | struct cpdma_chan *chan; | ||
| 475 | int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4; | ||
| 476 | unsigned long flags; | ||
| 477 | |||
| 478 | if (__chan_linear(chan_num) >= ctlr->num_chan) | ||
| 479 | return NULL; | ||
| 480 | |||
| 481 | ret = -ENOMEM; | ||
| 482 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); | ||
| 483 | if (!chan) | ||
| 484 | goto err_chan_alloc; | ||
| 485 | |||
| 486 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 487 | ret = -EBUSY; | ||
| 488 | if (ctlr->channels[chan_num]) | ||
| 489 | goto err_chan_busy; | ||
| 490 | |||
| 491 | chan->ctlr = ctlr; | ||
| 492 | chan->state = CPDMA_STATE_IDLE; | ||
| 493 | chan->chan_num = chan_num; | ||
| 494 | chan->handler = handler; | ||
| 495 | |||
| 496 | if (is_rx_chan(chan)) { | ||
| 497 | chan->hdp = ctlr->params.rxhdp + offset; | ||
| 498 | chan->cp = ctlr->params.rxcp + offset; | ||
| 499 | chan->rxfree = ctlr->params.rxfree + offset; | ||
| 500 | chan->int_set = CPDMA_RXINTMASKSET; | ||
| 501 | chan->int_clear = CPDMA_RXINTMASKCLEAR; | ||
| 502 | chan->td = CPDMA_RXTEARDOWN; | ||
| 503 | chan->dir = DMA_FROM_DEVICE; | ||
| 504 | } else { | ||
| 505 | chan->hdp = ctlr->params.txhdp + offset; | ||
| 506 | chan->cp = ctlr->params.txcp + offset; | ||
| 507 | chan->int_set = CPDMA_TXINTMASKSET; | ||
| 508 | chan->int_clear = CPDMA_TXINTMASKCLEAR; | ||
| 509 | chan->td = CPDMA_TXTEARDOWN; | ||
| 510 | chan->dir = DMA_TO_DEVICE; | ||
| 511 | } | ||
| 512 | chan->mask = BIT(chan_linear(chan)); | ||
| 513 | |||
| 514 | spin_lock_init(&chan->lock); | ||
| 515 | |||
| 516 | ctlr->channels[chan_num] = chan; | ||
| 517 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 518 | return chan; | ||
| 519 | |||
| 520 | err_chan_busy: | ||
| 521 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 522 | kfree(chan); | ||
| 523 | err_chan_alloc: | ||
| 524 | return ERR_PTR(ret); | ||
| 525 | } | ||
| 526 | |||
| 527 | int cpdma_chan_destroy(struct cpdma_chan *chan) | ||
| 528 | { | ||
| 529 | struct cpdma_ctlr *ctlr = chan->ctlr; | ||
| 530 | unsigned long flags; | ||
| 531 | |||
| 532 | if (!chan) | ||
| 533 | return -EINVAL; | ||
| 534 | |||
| 535 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 536 | if (chan->state != CPDMA_STATE_IDLE) | ||
| 537 | cpdma_chan_stop(chan); | ||
| 538 | ctlr->channels[chan->chan_num] = NULL; | ||
| 539 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 540 | kfree(chan); | ||
| 541 | return 0; | ||
| 542 | } | ||
| 543 | |||
| 544 | int cpdma_chan_get_stats(struct cpdma_chan *chan, | ||
| 545 | struct cpdma_chan_stats *stats) | ||
| 546 | { | ||
| 547 | unsigned long flags; | ||
| 548 | if (!chan) | ||
| 549 | return -EINVAL; | ||
| 550 | spin_lock_irqsave(&chan->lock, flags); | ||
| 551 | memcpy(stats, &chan->stats, sizeof(*stats)); | ||
| 552 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 556 | int cpdma_chan_dump(struct cpdma_chan *chan) | ||
| 557 | { | ||
| 558 | unsigned long flags; | ||
| 559 | struct device *dev = chan->ctlr->dev; | ||
| 560 | |||
| 561 | spin_lock_irqsave(&chan->lock, flags); | ||
| 562 | |||
| 563 | dev_info(dev, "channel %d (%s %d) state %s", | ||
| 564 | chan->chan_num, is_rx_chan(chan) ? "rx" : "tx", | ||
| 565 | chan_linear(chan), cpdma_state_str[chan->state]); | ||
| 566 | dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp)); | ||
| 567 | dev_info(dev, "\tcp: %x\n", chan_read(chan, cp)); | ||
| 568 | if (chan->rxfree) { | ||
| 569 | dev_info(dev, "\trxfree: %x\n", | ||
| 570 | chan_read(chan, rxfree)); | ||
| 571 | } | ||
| 572 | |||
| 573 | dev_info(dev, "\tstats head_enqueue: %d\n", | ||
| 574 | chan->stats.head_enqueue); | ||
| 575 | dev_info(dev, "\tstats tail_enqueue: %d\n", | ||
| 576 | chan->stats.tail_enqueue); | ||
| 577 | dev_info(dev, "\tstats pad_enqueue: %d\n", | ||
| 578 | chan->stats.pad_enqueue); | ||
| 579 | dev_info(dev, "\tstats misqueued: %d\n", | ||
| 580 | chan->stats.misqueued); | ||
| 581 | dev_info(dev, "\tstats desc_alloc_fail: %d\n", | ||
| 582 | chan->stats.desc_alloc_fail); | ||
| 583 | dev_info(dev, "\tstats pad_alloc_fail: %d\n", | ||
| 584 | chan->stats.pad_alloc_fail); | ||
| 585 | dev_info(dev, "\tstats runt_receive_buff: %d\n", | ||
| 586 | chan->stats.runt_receive_buff); | ||
| 587 | dev_info(dev, "\tstats runt_transmit_buff: %d\n", | ||
| 588 | chan->stats.runt_transmit_buff); | ||
| 589 | dev_info(dev, "\tstats empty_dequeue: %d\n", | ||
| 590 | chan->stats.empty_dequeue); | ||
| 591 | dev_info(dev, "\tstats busy_dequeue: %d\n", | ||
| 592 | chan->stats.busy_dequeue); | ||
| 593 | dev_info(dev, "\tstats good_dequeue: %d\n", | ||
| 594 | chan->stats.good_dequeue); | ||
| 595 | dev_info(dev, "\tstats requeue: %d\n", | ||
| 596 | chan->stats.requeue); | ||
| 597 | dev_info(dev, "\tstats teardown_dequeue: %d\n", | ||
| 598 | chan->stats.teardown_dequeue); | ||
| 599 | |||
| 600 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 601 | return 0; | ||
| 602 | } | ||
| 603 | |||
| 604 | static void __cpdma_chan_submit(struct cpdma_chan *chan, | ||
| 605 | struct cpdma_desc __iomem *desc) | ||
| 606 | { | ||
| 607 | struct cpdma_ctlr *ctlr = chan->ctlr; | ||
| 608 | struct cpdma_desc __iomem *prev = chan->tail; | ||
| 609 | struct cpdma_desc_pool *pool = ctlr->pool; | ||
| 610 | dma_addr_t desc_dma; | ||
| 611 | u32 mode; | ||
| 612 | |||
| 613 | desc_dma = desc_phys(pool, desc); | ||
| 614 | |||
| 615 | /* simple case - idle channel */ | ||
| 616 | if (!chan->head) { | ||
| 617 | chan->stats.head_enqueue++; | ||
| 618 | chan->head = desc; | ||
| 619 | chan->tail = desc; | ||
| 620 | if (chan->state == CPDMA_STATE_ACTIVE) | ||
| 621 | chan_write(chan, hdp, desc_dma); | ||
| 622 | return; | ||
| 623 | } | ||
| 624 | |||
| 625 | /* first chain the descriptor at the tail of the list */ | ||
| 626 | desc_write(prev, hw_next, desc_dma); | ||
| 627 | chan->tail = desc; | ||
| 628 | chan->stats.tail_enqueue++; | ||
| 629 | |||
| 630 | /* next check if EOQ has been triggered already */ | ||
| 631 | mode = desc_read(prev, hw_mode); | ||
| 632 | if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) && | ||
| 633 | (chan->state == CPDMA_STATE_ACTIVE)) { | ||
| 634 | desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ); | ||
| 635 | chan_write(chan, hdp, desc_dma); | ||
| 636 | chan->stats.misqueued++; | ||
| 637 | } | ||
| 638 | } | ||
| 639 | |||
| 640 | int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, | ||
| 641 | int len, gfp_t gfp_mask) | ||
| 642 | { | ||
| 643 | struct cpdma_ctlr *ctlr = chan->ctlr; | ||
| 644 | struct cpdma_desc __iomem *desc; | ||
| 645 | dma_addr_t buffer; | ||
| 646 | unsigned long flags; | ||
| 647 | u32 mode; | ||
| 648 | int ret = 0; | ||
| 649 | |||
| 650 | spin_lock_irqsave(&chan->lock, flags); | ||
| 651 | |||
| 652 | if (chan->state == CPDMA_STATE_TEARDOWN) { | ||
| 653 | ret = -EINVAL; | ||
| 654 | goto unlock_ret; | ||
| 655 | } | ||
| 656 | |||
| 657 | desc = cpdma_desc_alloc(ctlr->pool, 1); | ||
| 658 | if (!desc) { | ||
| 659 | chan->stats.desc_alloc_fail++; | ||
| 660 | ret = -ENOMEM; | ||
| 661 | goto unlock_ret; | ||
| 662 | } | ||
| 663 | |||
| 664 | if (len < ctlr->params.min_packet_size) { | ||
| 665 | len = ctlr->params.min_packet_size; | ||
| 666 | chan->stats.runt_transmit_buff++; | ||
| 667 | } | ||
| 668 | |||
| 669 | buffer = dma_map_single(ctlr->dev, data, len, chan->dir); | ||
| 670 | mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; | ||
| 671 | |||
| 672 | desc_write(desc, hw_next, 0); | ||
| 673 | desc_write(desc, hw_buffer, buffer); | ||
| 674 | desc_write(desc, hw_len, len); | ||
| 675 | desc_write(desc, hw_mode, mode | len); | ||
| 676 | desc_write(desc, sw_token, token); | ||
| 677 | desc_write(desc, sw_buffer, buffer); | ||
| 678 | desc_write(desc, sw_len, len); | ||
| 679 | |||
| 680 | __cpdma_chan_submit(chan, desc); | ||
| 681 | |||
| 682 | if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) | ||
| 683 | chan_write(chan, rxfree, 1); | ||
| 684 | |||
| 685 | chan->count++; | ||
| 686 | |||
| 687 | unlock_ret: | ||
| 688 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 689 | return ret; | ||
| 690 | } | ||
| 691 | |||
| 692 | static void __cpdma_chan_free(struct cpdma_chan *chan, | ||
| 693 | struct cpdma_desc __iomem *desc, | ||
| 694 | int outlen, int status) | ||
| 695 | { | ||
| 696 | struct cpdma_ctlr *ctlr = chan->ctlr; | ||
| 697 | struct cpdma_desc_pool *pool = ctlr->pool; | ||
| 698 | dma_addr_t buff_dma; | ||
| 699 | int origlen; | ||
| 700 | void *token; | ||
| 701 | |||
| 702 | token = (void *)desc_read(desc, sw_token); | ||
| 703 | buff_dma = desc_read(desc, sw_buffer); | ||
| 704 | origlen = desc_read(desc, sw_len); | ||
| 705 | |||
| 706 | dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir); | ||
| 707 | cpdma_desc_free(pool, desc, 1); | ||
| 708 | (*chan->handler)(token, outlen, status); | ||
| 709 | } | ||
| 710 | |||
| 711 | static int __cpdma_chan_process(struct cpdma_chan *chan) | ||
| 712 | { | ||
| 713 | struct cpdma_ctlr *ctlr = chan->ctlr; | ||
| 714 | struct cpdma_desc __iomem *desc; | ||
| 715 | int status, outlen; | ||
| 716 | struct cpdma_desc_pool *pool = ctlr->pool; | ||
| 717 | dma_addr_t desc_dma; | ||
| 718 | unsigned long flags; | ||
| 719 | |||
| 720 | spin_lock_irqsave(&chan->lock, flags); | ||
| 721 | |||
| 722 | desc = chan->head; | ||
| 723 | if (!desc) { | ||
| 724 | chan->stats.empty_dequeue++; | ||
| 725 | status = -ENOENT; | ||
| 726 | goto unlock_ret; | ||
| 727 | } | ||
| 728 | desc_dma = desc_phys(pool, desc); | ||
| 729 | |||
| 730 | status = __raw_readl(&desc->hw_mode); | ||
| 731 | outlen = status & 0x7ff; | ||
| 732 | if (status & CPDMA_DESC_OWNER) { | ||
| 733 | chan->stats.busy_dequeue++; | ||
| 734 | status = -EBUSY; | ||
| 735 | goto unlock_ret; | ||
| 736 | } | ||
| 737 | status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); | ||
| 738 | |||
| 739 | chan->head = desc_from_phys(pool, desc_read(desc, hw_next)); | ||
| 740 | chan_write(chan, cp, desc_dma); | ||
| 741 | chan->count--; | ||
| 742 | chan->stats.good_dequeue++; | ||
| 743 | |||
| 744 | if (status & CPDMA_DESC_EOQ) { | ||
| 745 | chan->stats.requeue++; | ||
| 746 | chan_write(chan, hdp, desc_phys(pool, chan->head)); | ||
| 747 | } | ||
| 748 | |||
| 749 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 750 | |||
| 751 | __cpdma_chan_free(chan, desc, outlen, status); | ||
| 752 | return status; | ||
| 753 | |||
| 754 | unlock_ret: | ||
| 755 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 756 | return status; | ||
| 757 | } | ||
| 758 | |||
| 759 | int cpdma_chan_process(struct cpdma_chan *chan, int quota) | ||
| 760 | { | ||
| 761 | int used = 0, ret = 0; | ||
| 762 | |||
| 763 | if (chan->state != CPDMA_STATE_ACTIVE) | ||
| 764 | return -EINVAL; | ||
| 765 | |||
| 766 | while (used < quota) { | ||
| 767 | ret = __cpdma_chan_process(chan); | ||
| 768 | if (ret < 0) | ||
| 769 | break; | ||
| 770 | used++; | ||
| 771 | } | ||
| 772 | return used; | ||
| 773 | } | ||
| 774 | |||
| 775 | int cpdma_chan_start(struct cpdma_chan *chan) | ||
| 776 | { | ||
| 777 | struct cpdma_ctlr *ctlr = chan->ctlr; | ||
| 778 | struct cpdma_desc_pool *pool = ctlr->pool; | ||
| 779 | unsigned long flags; | ||
| 780 | |||
| 781 | spin_lock_irqsave(&chan->lock, flags); | ||
| 782 | if (chan->state != CPDMA_STATE_IDLE) { | ||
| 783 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 784 | return -EBUSY; | ||
| 785 | } | ||
| 786 | if (ctlr->state != CPDMA_STATE_ACTIVE) { | ||
| 787 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 788 | return -EINVAL; | ||
| 789 | } | ||
| 790 | dma_reg_write(ctlr, chan->int_set, chan->mask); | ||
| 791 | chan->state = CPDMA_STATE_ACTIVE; | ||
| 792 | if (chan->head) { | ||
| 793 | chan_write(chan, hdp, desc_phys(pool, chan->head)); | ||
| 794 | if (chan->rxfree) | ||
| 795 | chan_write(chan, rxfree, chan->count); | ||
| 796 | } | ||
| 797 | |||
| 798 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 799 | return 0; | ||
| 800 | } | ||
| 801 | |||
| 802 | int cpdma_chan_stop(struct cpdma_chan *chan) | ||
| 803 | { | ||
| 804 | struct cpdma_ctlr *ctlr = chan->ctlr; | ||
| 805 | struct cpdma_desc_pool *pool = ctlr->pool; | ||
| 806 | unsigned long flags; | ||
| 807 | int ret; | ||
| 808 | unsigned long timeout; | ||
| 809 | |||
| 810 | spin_lock_irqsave(&chan->lock, flags); | ||
| 811 | if (chan->state != CPDMA_STATE_ACTIVE) { | ||
| 812 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 813 | return -EINVAL; | ||
| 814 | } | ||
| 815 | |||
| 816 | chan->state = CPDMA_STATE_TEARDOWN; | ||
| 817 | dma_reg_write(ctlr, chan->int_clear, chan->mask); | ||
| 818 | |||
| 819 | /* trigger teardown */ | ||
| 820 | dma_reg_write(ctlr, chan->td, chan->chan_num); | ||
| 821 | |||
| 822 | /* wait for teardown complete */ | ||
| 823 | timeout = jiffies + HZ/10; /* 100 msec */ | ||
| 824 | while (time_before(jiffies, timeout)) { | ||
| 825 | u32 cp = chan_read(chan, cp); | ||
| 826 | if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) | ||
| 827 | break; | ||
| 828 | cpu_relax(); | ||
| 829 | } | ||
| 830 | WARN_ON(!time_before(jiffies, timeout)); | ||
| 831 | chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); | ||
| 832 | |||
| 833 | /* handle completed packets */ | ||
| 834 | do { | ||
| 835 | ret = __cpdma_chan_process(chan); | ||
| 836 | if (ret < 0) | ||
| 837 | break; | ||
| 838 | } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); | ||
| 839 | |||
| 840 | /* remaining packets haven't been tx/rx'ed, clean them up */ | ||
| 841 | while (chan->head) { | ||
| 842 | struct cpdma_desc __iomem *desc = chan->head; | ||
| 843 | dma_addr_t next_dma; | ||
| 844 | |||
| 845 | next_dma = desc_read(desc, hw_next); | ||
| 846 | chan->head = desc_from_phys(pool, next_dma); | ||
| 847 | chan->stats.teardown_dequeue++; | ||
| 848 | |||
| 849 | /* issue callback without locks held */ | ||
| 850 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 851 | __cpdma_chan_free(chan, desc, 0, -ENOSYS); | ||
| 852 | spin_lock_irqsave(&chan->lock, flags); | ||
| 853 | } | ||
| 854 | |||
| 855 | chan->state = CPDMA_STATE_IDLE; | ||
| 856 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) | ||
| 861 | { | ||
| 862 | unsigned long flags; | ||
| 863 | |||
| 864 | spin_lock_irqsave(&chan->lock, flags); | ||
| 865 | if (chan->state != CPDMA_STATE_ACTIVE) { | ||
| 866 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 867 | return -EINVAL; | ||
| 868 | } | ||
| 869 | |||
| 870 | dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear, | ||
| 871 | chan->mask); | ||
| 872 | spin_unlock_irqrestore(&chan->lock, flags); | ||
| 873 | |||
| 874 | return 0; | ||
| 875 | } | ||
| 876 | |||
| 877 | struct cpdma_control_info { | ||
| 878 | u32 reg; | ||
| 879 | u32 shift, mask; | ||
| 880 | int access; | ||
| 881 | #define ACCESS_RO BIT(0) | ||
| 882 | #define ACCESS_WO BIT(1) | ||
| 883 | #define ACCESS_RW (ACCESS_RO | ACCESS_WO) | ||
| 884 | }; | ||
| 885 | |||
| 886 | struct cpdma_control_info controls[] = { | ||
| 887 | [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, | ||
| 888 | [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, | ||
| 889 | [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, | ||
| 890 | [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW}, | ||
| 891 | [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW}, | ||
| 892 | [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO}, | ||
| 893 | [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW}, | ||
| 894 | [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW}, | ||
| 895 | [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW}, | ||
| 896 | [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW}, | ||
| 897 | [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW}, | ||
| 898 | }; | ||
| 899 | |||
| 900 | int cpdma_control_get(struct cpdma_ctlr *ctlr, int control) | ||
| 901 | { | ||
| 902 | unsigned long flags; | ||
| 903 | struct cpdma_control_info *info = &controls[control]; | ||
| 904 | int ret; | ||
| 905 | |||
| 906 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 907 | |||
| 908 | ret = -ENOTSUPP; | ||
| 909 | if (!ctlr->params.has_ext_regs) | ||
| 910 | goto unlock_ret; | ||
| 911 | |||
| 912 | ret = -EINVAL; | ||
| 913 | if (ctlr->state != CPDMA_STATE_ACTIVE) | ||
| 914 | goto unlock_ret; | ||
| 915 | |||
| 916 | ret = -ENOENT; | ||
| 917 | if (control < 0 || control >= ARRAY_SIZE(controls)) | ||
| 918 | goto unlock_ret; | ||
| 919 | |||
| 920 | ret = -EPERM; | ||
| 921 | if ((info->access & ACCESS_RO) != ACCESS_RO) | ||
| 922 | goto unlock_ret; | ||
| 923 | |||
| 924 | ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask; | ||
| 925 | |||
| 926 | unlock_ret: | ||
| 927 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 928 | return ret; | ||
| 929 | } | ||
| 930 | |||
| 931 | int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value) | ||
| 932 | { | ||
| 933 | unsigned long flags; | ||
| 934 | struct cpdma_control_info *info = &controls[control]; | ||
| 935 | int ret; | ||
| 936 | u32 val; | ||
| 937 | |||
| 938 | spin_lock_irqsave(&ctlr->lock, flags); | ||
| 939 | |||
| 940 | ret = -ENOTSUPP; | ||
| 941 | if (!ctlr->params.has_ext_regs) | ||
| 942 | goto unlock_ret; | ||
| 943 | |||
| 944 | ret = -EINVAL; | ||
| 945 | if (ctlr->state != CPDMA_STATE_ACTIVE) | ||
| 946 | goto unlock_ret; | ||
| 947 | |||
| 948 | ret = -ENOENT; | ||
| 949 | if (control < 0 || control >= ARRAY_SIZE(controls)) | ||
| 950 | goto unlock_ret; | ||
| 951 | |||
| 952 | ret = -EPERM; | ||
| 953 | if ((info->access & ACCESS_WO) != ACCESS_WO) | ||
| 954 | goto unlock_ret; | ||
| 955 | |||
| 956 | val = dma_reg_read(ctlr, info->reg); | ||
| 957 | val &= ~(info->mask << info->shift); | ||
| 958 | val |= (value & info->mask) << info->shift; | ||
| 959 | dma_reg_write(ctlr, info->reg, val); | ||
| 960 | ret = 0; | ||
| 961 | |||
| 962 | unlock_ret: | ||
| 963 | spin_unlock_irqrestore(&ctlr->lock, flags); | ||
| 964 | return ret; | ||
| 965 | } | ||
diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h new file mode 100644 index 000000000000..868e50ebde45 --- /dev/null +++ b/drivers/net/davinci_cpdma.h | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | /* | ||
| 2 | * Texas Instruments CPDMA Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Texas Instruments | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation version 2. | ||
| 9 | * | ||
| 10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 11 | * kind, whether express or implied; without even the implied warranty | ||
| 12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | #ifndef __DAVINCI_CPDMA_H__ | ||
| 16 | #define __DAVINCI_CPDMA_H__ | ||
| 17 | |||
| 18 | #define CPDMA_MAX_CHANNELS BITS_PER_LONG | ||
| 19 | |||
| 20 | #define tx_chan_num(chan) (chan) | ||
| 21 | #define rx_chan_num(chan) ((chan) + CPDMA_MAX_CHANNELS) | ||
| 22 | #define is_rx_chan(chan) ((chan)->chan_num >= CPDMA_MAX_CHANNELS) | ||
| 23 | #define is_tx_chan(chan) (!is_rx_chan(chan)) | ||
| 24 | #define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1)) | ||
| 25 | #define chan_linear(chan) __chan_linear((chan)->chan_num) | ||
| 26 | |||
| 27 | struct cpdma_params { | ||
| 28 | struct device *dev; | ||
| 29 | void __iomem *dmaregs; | ||
| 30 | void __iomem *txhdp, *rxhdp, *txcp, *rxcp; | ||
| 31 | void __iomem *rxthresh, *rxfree; | ||
| 32 | int num_chan; | ||
| 33 | bool has_soft_reset; | ||
| 34 | int min_packet_size; | ||
| 35 | u32 desc_mem_phys; | ||
| 36 | int desc_mem_size; | ||
| 37 | int desc_align; | ||
| 38 | |||
| 39 | /* | ||
| 40 | * Some instances of embedded cpdma controllers have extra control and | ||
| 41 | * status registers. The following flag enables access to these | ||
| 42 | * "extended" registers. | ||
| 43 | */ | ||
| 44 | bool has_ext_regs; | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct cpdma_chan_stats { | ||
| 48 | u32 head_enqueue; | ||
| 49 | u32 tail_enqueue; | ||
| 50 | u32 pad_enqueue; | ||
| 51 | u32 misqueued; | ||
| 52 | u32 desc_alloc_fail; | ||
| 53 | u32 pad_alloc_fail; | ||
| 54 | u32 runt_receive_buff; | ||
| 55 | u32 runt_transmit_buff; | ||
| 56 | u32 empty_dequeue; | ||
| 57 | u32 busy_dequeue; | ||
| 58 | u32 good_dequeue; | ||
| 59 | u32 requeue; | ||
| 60 | u32 teardown_dequeue; | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct cpdma_ctlr; | ||
| 64 | struct cpdma_chan; | ||
| 65 | |||
| 66 | typedef void (*cpdma_handler_fn)(void *token, int len, int status); | ||
| 67 | |||
| 68 | struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params); | ||
| 69 | int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr); | ||
| 70 | int cpdma_ctlr_start(struct cpdma_ctlr *ctlr); | ||
| 71 | int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr); | ||
| 72 | int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr); | ||
| 73 | |||
| 74 | struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, | ||
| 75 | cpdma_handler_fn handler); | ||
| 76 | int cpdma_chan_destroy(struct cpdma_chan *chan); | ||
| 77 | int cpdma_chan_start(struct cpdma_chan *chan); | ||
| 78 | int cpdma_chan_stop(struct cpdma_chan *chan); | ||
| 79 | int cpdma_chan_dump(struct cpdma_chan *chan); | ||
| 80 | |||
| 81 | int cpdma_chan_get_stats(struct cpdma_chan *chan, | ||
| 82 | struct cpdma_chan_stats *stats); | ||
| 83 | int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, | ||
| 84 | int len, gfp_t gfp_mask); | ||
| 85 | int cpdma_chan_process(struct cpdma_chan *chan, int quota); | ||
| 86 | |||
| 87 | int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable); | ||
| 88 | void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr); | ||
| 89 | int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable); | ||
| 90 | |||
| 91 | enum cpdma_control { | ||
| 92 | CPDMA_CMD_IDLE, /* write-only */ | ||
| 93 | CPDMA_COPY_ERROR_FRAMES, /* read-write */ | ||
| 94 | CPDMA_RX_OFF_LEN_UPDATE, /* read-write */ | ||
| 95 | CPDMA_RX_OWNERSHIP_FLIP, /* read-write */ | ||
| 96 | CPDMA_TX_PRIO_FIXED, /* read-write */ | ||
| 97 | CPDMA_STAT_IDLE, /* read-only */ | ||
| 98 | CPDMA_STAT_TX_ERR_CHAN, /* read-only */ | ||
| 99 | CPDMA_STAT_TX_ERR_CODE, /* read-only */ | ||
| 100 | CPDMA_STAT_RX_ERR_CHAN, /* read-only */ | ||
| 101 | CPDMA_STAT_RX_ERR_CODE, /* read-only */ | ||
| 102 | CPDMA_RX_BUFFER_OFFSET, /* read-write */ | ||
| 103 | }; | ||
| 104 | |||
| 105 | int cpdma_control_get(struct cpdma_ctlr *ctlr, int control); | ||
| 106 | int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value); | ||
| 107 | |||
| 108 | #endif | ||
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 7fbd052ddb0a..2a628d17d178 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c | |||
| @@ -63,6 +63,8 @@ | |||
| 63 | #include <asm/irq.h> | 63 | #include <asm/irq.h> |
| 64 | #include <asm/page.h> | 64 | #include <asm/page.h> |
| 65 | 65 | ||
| 66 | #include "davinci_cpdma.h" | ||
| 67 | |||
| 66 | static int debug_level; | 68 | static int debug_level; |
| 67 | module_param(debug_level, int, 0); | 69 | module_param(debug_level, int, 0); |
| 68 | MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); | 70 | MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); |
| @@ -113,7 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; | |||
| 113 | #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) | 115 | #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) |
| 114 | #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ | 116 | #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ |
| 115 | #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ | 117 | #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ |
| 116 | #define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */ | 118 | #define EMAC_DEF_RX_NUM_DESC (128) |
| 117 | #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ | 119 | #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ |
| 118 | #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ | 120 | #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ |
| 119 | #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ | 121 | #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ |
| @@ -125,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; | |||
| 125 | /* EMAC register related defines */ | 127 | /* EMAC register related defines */ |
| 126 | #define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) | 128 | #define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) |
| 127 | #define EMAC_NUM_MULTICAST_BITS (64) | 129 | #define EMAC_NUM_MULTICAST_BITS (64) |
| 128 | #define EMAC_TEARDOWN_VALUE (0xFFFFFFFC) | ||
| 129 | #define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) | 130 | #define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) |
| 130 | #define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) | 131 | #define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) |
| 131 | #define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) | 132 | #define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) |
| @@ -212,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; | |||
| 212 | #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ | 213 | #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ |
| 213 | 214 | ||
| 214 | /* EMAC Peripheral Device Register Memory Layout structure */ | 215 | /* EMAC Peripheral Device Register Memory Layout structure */ |
| 215 | #define EMAC_TXIDVER 0x0 | ||
| 216 | #define EMAC_TXCONTROL 0x4 | ||
| 217 | #define EMAC_TXTEARDOWN 0x8 | ||
| 218 | #define EMAC_RXIDVER 0x10 | ||
| 219 | #define EMAC_RXCONTROL 0x14 | ||
| 220 | #define EMAC_RXTEARDOWN 0x18 | ||
| 221 | #define EMAC_TXINTSTATRAW 0x80 | ||
| 222 | #define EMAC_TXINTSTATMASKED 0x84 | ||
| 223 | #define EMAC_TXINTMASKSET 0x88 | ||
| 224 | #define EMAC_TXINTMASKCLEAR 0x8C | ||
| 225 | #define EMAC_MACINVECTOR 0x90 | 216 | #define EMAC_MACINVECTOR 0x90 |
| 226 | 217 | ||
| 227 | #define EMAC_DM646X_MACEOIVECTOR 0x94 | 218 | #define EMAC_DM646X_MACEOIVECTOR 0x94 |
| 228 | 219 | ||
| 229 | #define EMAC_RXINTSTATRAW 0xA0 | ||
| 230 | #define EMAC_RXINTSTATMASKED 0xA4 | ||
| 231 | #define EMAC_RXINTMASKSET 0xA8 | ||
| 232 | #define EMAC_RXINTMASKCLEAR 0xAC | ||
| 233 | #define EMAC_MACINTSTATRAW 0xB0 | 220 | #define EMAC_MACINTSTATRAW 0xB0 |
| 234 | #define EMAC_MACINTSTATMASKED 0xB4 | 221 | #define EMAC_MACINTSTATMASKED 0xB4 |
| 235 | #define EMAC_MACINTMASKSET 0xB8 | 222 | #define EMAC_MACINTMASKSET 0xB8 |
| @@ -256,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; | |||
| 256 | #define EMAC_MACADDRHI 0x504 | 243 | #define EMAC_MACADDRHI 0x504 |
| 257 | #define EMAC_MACINDEX 0x508 | 244 | #define EMAC_MACINDEX 0x508 |
| 258 | 245 | ||
| 259 | /* EMAC HDP and Completion registors */ | ||
| 260 | #define EMAC_TXHDP(ch) (0x600 + (ch * 4)) | ||
| 261 | #define EMAC_RXHDP(ch) (0x620 + (ch * 4)) | ||
| 262 | #define EMAC_TXCP(ch) (0x640 + (ch * 4)) | ||
| 263 | #define EMAC_RXCP(ch) (0x660 + (ch * 4)) | ||
| 264 | |||
| 265 | /* EMAC statistics registers */ | 246 | /* EMAC statistics registers */ |
| 266 | #define EMAC_RXGOODFRAMES 0x200 | 247 | #define EMAC_RXGOODFRAMES 0x200 |
| 267 | #define EMAC_RXBCASTFRAMES 0x204 | 248 | #define EMAC_RXBCASTFRAMES 0x204 |
| @@ -303,25 +284,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; | |||
| 303 | #define EMAC_DM644X_INTMIN_INTVL 0x1 | 284 | #define EMAC_DM644X_INTMIN_INTVL 0x1 |
| 304 | #define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) | 285 | #define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) |
| 305 | 286 | ||
| 306 | /* EMAC MDIO related */ | ||
| 307 | /* Mask & Control defines */ | ||
| 308 | #define MDIO_CONTROL_CLKDIV (0xFF) | ||
| 309 | #define MDIO_CONTROL_ENABLE BIT(30) | ||
| 310 | #define MDIO_USERACCESS_GO BIT(31) | ||
| 311 | #define MDIO_USERACCESS_WRITE BIT(30) | ||
| 312 | #define MDIO_USERACCESS_READ (0) | ||
| 313 | #define MDIO_USERACCESS_REGADR (0x1F << 21) | ||
| 314 | #define MDIO_USERACCESS_PHYADR (0x1F << 16) | ||
| 315 | #define MDIO_USERACCESS_DATA (0xFFFF) | ||
| 316 | #define MDIO_USERPHYSEL_LINKSEL BIT(7) | ||
| 317 | #define MDIO_VER_MODID (0xFFFF << 16) | ||
| 318 | #define MDIO_VER_REVMAJ (0xFF << 8) | ||
| 319 | #define MDIO_VER_REVMIN (0xFF) | ||
| 320 | |||
| 321 | #define MDIO_USERACCESS(inst) (0x80 + (inst * 8)) | ||
| 322 | #define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8)) | ||
| 323 | #define MDIO_CONTROL (0x04) | ||
| 324 | |||
| 325 | /* EMAC DM646X control module registers */ | 287 | /* EMAC DM646X control module registers */ |
| 326 | #define EMAC_DM646X_CMINTCTRL 0x0C | 288 | #define EMAC_DM646X_CMINTCTRL 0x0C |
| 327 | #define EMAC_DM646X_CMRXINTEN 0x14 | 289 | #define EMAC_DM646X_CMRXINTEN 0x14 |
| @@ -345,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; | |||
| 345 | /* EMAC Stats Clear Mask */ | 307 | /* EMAC Stats Clear Mask */ |
| 346 | #define EMAC_STATS_CLR_MASK (0xFFFFFFFF) | 308 | #define EMAC_STATS_CLR_MASK (0xFFFFFFFF) |
| 347 | 309 | ||
| 348 | /** net_buf_obj: EMAC network bufferdata structure | ||
| 349 | * | ||
| 350 | * EMAC network buffer data structure | ||
| 351 | */ | ||
| 352 | struct emac_netbufobj { | ||
| 353 | void *buf_token; | ||
| 354 | char *data_ptr; | ||
| 355 | int length; | ||
| 356 | }; | ||
| 357 | |||
| 358 | /** net_pkt_obj: EMAC network packet data structure | ||
| 359 | * | ||
| 360 | * EMAC network packet data structure - supports buffer list (for future) | ||
| 361 | */ | ||
| 362 | struct emac_netpktobj { | ||
| 363 | void *pkt_token; /* data token may hold tx/rx chan id */ | ||
| 364 | struct emac_netbufobj *buf_list; /* array of network buffer objects */ | ||
| 365 | int num_bufs; | ||
| 366 | int pkt_length; | ||
| 367 | }; | ||
| 368 | |||
| 369 | /** emac_tx_bd: EMAC TX Buffer descriptor data structure | ||
| 370 | * | ||
| 371 | * EMAC TX Buffer descriptor data structure | ||
| 372 | */ | ||
| 373 | struct emac_tx_bd { | ||
| 374 | int h_next; | ||
| 375 | int buff_ptr; | ||
| 376 | int off_b_len; | ||
| 377 | int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */ | ||
| 378 | struct emac_tx_bd __iomem *next; | ||
| 379 | void *buf_token; | ||
| 380 | }; | ||
| 381 | |||
| 382 | /** emac_txch: EMAC TX Channel data structure | ||
| 383 | * | ||
| 384 | * EMAC TX Channel data structure | ||
| 385 | */ | ||
| 386 | struct emac_txch { | ||
| 387 | /* Config related */ | ||
| 388 | u32 num_bd; | ||
| 389 | u32 service_max; | ||
| 390 | |||
| 391 | /* CPPI specific */ | ||
| 392 | u32 alloc_size; | ||
| 393 | void __iomem *bd_mem; | ||
| 394 | struct emac_tx_bd __iomem *bd_pool_head; | ||
| 395 | struct emac_tx_bd __iomem *active_queue_head; | ||
| 396 | struct emac_tx_bd __iomem *active_queue_tail; | ||
| 397 | struct emac_tx_bd __iomem *last_hw_bdprocessed; | ||
| 398 | u32 queue_active; | ||
| 399 | u32 teardown_pending; | ||
| 400 | u32 *tx_complete; | ||
| 401 | |||
| 402 | /** statistics */ | ||
| 403 | u32 proc_count; /* TX: # of times emac_tx_bdproc is called */ | ||
| 404 | u32 mis_queued_packets; | ||
| 405 | u32 queue_reinit; | ||
| 406 | u32 end_of_queue_add; | ||
| 407 | u32 out_of_tx_bd; | ||
| 408 | u32 no_active_pkts; /* IRQ when there were no packets to process */ | ||
| 409 | u32 active_queue_count; | ||
| 410 | }; | ||
| 411 | |||
| 412 | /** emac_rx_bd: EMAC RX Buffer descriptor data structure | ||
| 413 | * | ||
| 414 | * EMAC RX Buffer descriptor data structure | ||
| 415 | */ | ||
| 416 | struct emac_rx_bd { | ||
| 417 | int h_next; | ||
| 418 | int buff_ptr; | ||
| 419 | int off_b_len; | ||
| 420 | int mode; | ||
| 421 | struct emac_rx_bd __iomem *next; | ||
| 422 | void *data_ptr; | ||
| 423 | void *buf_token; | ||
| 424 | }; | ||
| 425 | |||
| 426 | /** emac_rxch: EMAC RX Channel data structure | ||
| 427 | * | ||
| 428 | * EMAC RX Channel data structure | ||
| 429 | */ | ||
| 430 | struct emac_rxch { | ||
| 431 | /* configuration info */ | ||
| 432 | u32 num_bd; | ||
| 433 | u32 service_max; | ||
| 434 | u32 buf_size; | ||
| 435 | char mac_addr[6]; | ||
| 436 | |||
| 437 | /** CPPI specific */ | ||
| 438 | u32 alloc_size; | ||
| 439 | void __iomem *bd_mem; | ||
| 440 | struct emac_rx_bd __iomem *bd_pool_head; | ||
| 441 | struct emac_rx_bd __iomem *active_queue_head; | ||
| 442 | struct emac_rx_bd __iomem *active_queue_tail; | ||
| 443 | u32 queue_active; | ||
| 444 | u32 teardown_pending; | ||
| 445 | |||
| 446 | /* packet and buffer objects */ | ||
| 447 | struct emac_netpktobj pkt_queue; | ||
| 448 | struct emac_netbufobj buf_queue; | ||
| 449 | |||
| 450 | /** statistics */ | ||
| 451 | u32 proc_count; /* number of times emac_rx_bdproc is called */ | ||
| 452 | u32 processed_bd; | ||
| 453 | u32 recycled_bd; | ||
| 454 | u32 out_of_rx_bd; | ||
| 455 | u32 out_of_rx_buffers; | ||
| 456 | u32 queue_reinit; | ||
| 457 | u32 end_of_queue_add; | ||
| 458 | u32 end_of_queue; | ||
| 459 | u32 mis_queued_packets; | ||
| 460 | }; | ||
| 461 | |||
| 462 | /* emac_priv: EMAC private data structure | 310 | /* emac_priv: EMAC private data structure |
| 463 | * | 311 | * |
| 464 | * EMAC adapter private data structure | 312 | * EMAC adapter private data structure |
| @@ -469,17 +317,13 @@ struct emac_priv { | |||
| 469 | struct platform_device *pdev; | 317 | struct platform_device *pdev; |
| 470 | struct napi_struct napi; | 318 | struct napi_struct napi; |
| 471 | char mac_addr[6]; | 319 | char mac_addr[6]; |
| 472 | spinlock_t tx_lock; | ||
| 473 | spinlock_t rx_lock; | ||
| 474 | void __iomem *remap_addr; | 320 | void __iomem *remap_addr; |
| 475 | u32 emac_base_phys; | 321 | u32 emac_base_phys; |
| 476 | void __iomem *emac_base; | 322 | void __iomem *emac_base; |
| 477 | void __iomem *ctrl_base; | 323 | void __iomem *ctrl_base; |
| 478 | void __iomem *emac_ctrl_ram; | 324 | struct cpdma_ctlr *dma; |
| 479 | u32 ctrl_ram_size; | 325 | struct cpdma_chan *txchan; |
| 480 | u32 hw_ram_addr; | 326 | struct cpdma_chan *rxchan; |
| 481 | struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; | ||
| 482 | struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; | ||
| 483 | u32 link; /* 1=link on, 0=link off */ | 327 | u32 link; /* 1=link on, 0=link off */ |
| 484 | u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ | 328 | u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ |
| 485 | u32 duplex; /* Link duplex: 0=Half, 1=Full */ | 329 | u32 duplex; /* Link duplex: 0=Half, 1=Full */ |
| @@ -493,13 +337,7 @@ struct emac_priv { | |||
| 493 | u32 mac_hash2; | 337 | u32 mac_hash2; |
| 494 | u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; | 338 | u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; |
| 495 | u32 rx_addr_type; | 339 | u32 rx_addr_type; |
| 496 | /* periodic timer required for MDIO polling */ | 340 | const char *phy_id; |
| 497 | struct timer_list periodic_timer; | ||
| 498 | u32 periodic_ticks; | ||
| 499 | u32 timer_active; | ||
| 500 | u32 phy_mask; | ||
| 501 | /* mii_bus,phy members */ | ||
| 502 | struct mii_bus *mii_bus; | ||
| 503 | struct phy_device *phydev; | 341 | struct phy_device *phydev; |
| 504 | spinlock_t lock; | 342 | spinlock_t lock; |
| 505 | /*platform specific members*/ | 343 | /*platform specific members*/ |
| @@ -510,19 +348,6 @@ struct emac_priv { | |||
| 510 | /* clock frequency for EMAC */ | 348 | /* clock frequency for EMAC */ |
| 511 | static struct clk *emac_clk; | 349 | static struct clk *emac_clk; |
| 512 | static unsigned long emac_bus_frequency; | 350 | static unsigned long emac_bus_frequency; |
| 513 | static unsigned long mdio_max_freq; | ||
| 514 | |||
| 515 | #define emac_virt_to_phys(addr, priv) \ | ||
| 516 | (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ | ||
| 517 | + priv->hw_ram_addr) | ||
| 518 | |||
| 519 | /* Cache macros - Packet buffers would be from skb pool which is cached */ | ||
| 520 | #define EMAC_VIRT_NOCACHE(addr) (addr) | ||
| 521 | |||
| 522 | /* DM644x does not have BD's in cached memory - so no cache functions */ | ||
| 523 | #define BD_CACHE_INVALIDATE(addr, size) | ||
| 524 | #define BD_CACHE_WRITEBACK(addr, size) | ||
| 525 | #define BD_CACHE_WRITEBACK_INVALIDATE(addr, size) | ||
| 526 | 351 | ||
| 527 | /* EMAC TX Host Error description strings */ | 352 | /* EMAC TX Host Error description strings */ |
| 528 | static char *emac_txhost_errcodes[16] = { | 353 | static char *emac_txhost_errcodes[16] = { |
| @@ -548,9 +373,6 @@ static char *emac_rxhost_errcodes[16] = { | |||
| 548 | #define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) | 373 | #define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) |
| 549 | #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) | 374 | #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) |
| 550 | 375 | ||
| 551 | #define emac_mdio_read(reg) ioread32(bus->priv + (reg)) | ||
| 552 | #define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg))) | ||
| 553 | |||
| 554 | /** | 376 | /** |
| 555 | * emac_dump_regs: Dump important EMAC registers to debug terminal | 377 | * emac_dump_regs: Dump important EMAC registers to debug terminal |
| 556 | * @priv: The DaVinci EMAC private adapter structure | 378 | * @priv: The DaVinci EMAC private adapter structure |
| @@ -569,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv) | |||
| 569 | emac_ctrl_read(EMAC_CTRL_EWCTL), | 391 | emac_ctrl_read(EMAC_CTRL_EWCTL), |
| 570 | emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); | 392 | emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); |
| 571 | } | 393 | } |
| 572 | dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", | ||
| 573 | emac_read(EMAC_TXIDVER), | ||
| 574 | ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), | ||
| 575 | emac_read(EMAC_RXIDVER), | ||
| 576 | ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled")); | ||
| 577 | dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\ | ||
| 578 | "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW), | ||
| 579 | emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET)); | ||
| 580 | dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\ | ||
| 581 | "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW), | ||
| 582 | emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET)); | ||
| 583 | dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\ | ||
| 584 | "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW), | ||
| 585 | emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR)); | ||
| 586 | dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", | 394 | dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", |
| 587 | emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); | 395 | emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); |
| 588 | dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ | 396 | dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ |
| @@ -591,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv) | |||
| 591 | dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ | 399 | dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ |
| 592 | "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), | 400 | "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), |
| 593 | emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); | 401 | emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); |
| 594 | dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n", | ||
| 595 | emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0))); | ||
| 596 | dev_info(emac_dev, "EMAC Statistics\n"); | 402 | dev_info(emac_dev, "EMAC Statistics\n"); |
| 597 | dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", | 403 | dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", |
| 598 | emac_read(EMAC_RXGOODFRAMES)); | 404 | emac_read(EMAC_RXGOODFRAMES)); |
| @@ -654,11 +460,10 @@ static void emac_dump_regs(struct emac_priv *priv) | |||
| 654 | emac_read(EMAC_RXMOFOVERRUNS)); | 460 | emac_read(EMAC_RXMOFOVERRUNS)); |
| 655 | dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", | 461 | dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", |
| 656 | emac_read(EMAC_RXDMAOVERRUNS)); | 462 | emac_read(EMAC_RXDMAOVERRUNS)); |
| 463 | |||
| 464 | cpdma_ctlr_dump(priv->dma); | ||
| 657 | } | 465 | } |
| 658 | 466 | ||
| 659 | /************************************************************************* | ||
| 660 | * EMAC MDIO/Phy Functionality | ||
| 661 | *************************************************************************/ | ||
| 662 | /** | 467 | /** |
| 663 | * emac_get_drvinfo: Get EMAC driver information | 468 | * emac_get_drvinfo: Get EMAC driver information |
| 664 | * @ndev: The DaVinci EMAC network adapter | 469 | * @ndev: The DaVinci EMAC network adapter |
| @@ -686,7 +491,7 @@ static int emac_get_settings(struct net_device *ndev, | |||
| 686 | struct ethtool_cmd *ecmd) | 491 | struct ethtool_cmd *ecmd) |
| 687 | { | 492 | { |
| 688 | struct emac_priv *priv = netdev_priv(ndev); | 493 | struct emac_priv *priv = netdev_priv(ndev); |
| 689 | if (priv->phy_mask) | 494 | if (priv->phydev) |
| 690 | return phy_ethtool_gset(priv->phydev, ecmd); | 495 | return phy_ethtool_gset(priv->phydev, ecmd); |
| 691 | else | 496 | else |
| 692 | return -EOPNOTSUPP; | 497 | return -EOPNOTSUPP; |
| @@ -704,7 +509,7 @@ static int emac_get_settings(struct net_device *ndev, | |||
| 704 | static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) | 509 | static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) |
| 705 | { | 510 | { |
| 706 | struct emac_priv *priv = netdev_priv(ndev); | 511 | struct emac_priv *priv = netdev_priv(ndev); |
| 707 | if (priv->phy_mask) | 512 | if (priv->phydev) |
| 708 | return phy_ethtool_sset(priv->phydev, ecmd); | 513 | return phy_ethtool_sset(priv->phydev, ecmd); |
| 709 | else | 514 | else |
| 710 | return -EOPNOTSUPP; | 515 | return -EOPNOTSUPP; |
| @@ -841,7 +646,7 @@ static void emac_update_phystatus(struct emac_priv *priv) | |||
| 841 | mac_control = emac_read(EMAC_MACCONTROL); | 646 | mac_control = emac_read(EMAC_MACCONTROL); |
| 842 | cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? | 647 | cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? |
| 843 | DUPLEX_FULL : DUPLEX_HALF; | 648 | DUPLEX_FULL : DUPLEX_HALF; |
| 844 | if (priv->phy_mask) | 649 | if (priv->phydev) |
| 845 | new_duplex = priv->phydev->duplex; | 650 | new_duplex = priv->phydev->duplex; |
| 846 | else | 651 | else |
| 847 | new_duplex = DUPLEX_FULL; | 652 | new_duplex = DUPLEX_FULL; |
| @@ -1184,371 +989,68 @@ static irqreturn_t emac_irq(int irq, void *dev_id) | |||
| 1184 | return IRQ_HANDLED; | 989 | return IRQ_HANDLED; |
| 1185 | } | 990 | } |
| 1186 | 991 | ||
| 1187 | /** EMAC on-chip buffer descriptor memory | 992 | static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) |
| 1188 | * | ||
| 1189 | * WARNING: Please note that the on chip memory is used for both TX and RX | ||
| 1190 | * buffer descriptor queues and is equally divided between TX and RX desc's | ||
| 1191 | * If the number of TX or RX descriptors change this memory pointers need | ||
| 1192 | * to be adjusted. If external memory is allocated then these pointers can | ||
| 1193 | * pointer to the memory | ||
| 1194 | * | ||
| 1195 | */ | ||
| 1196 | #define EMAC_TX_BD_MEM(priv) ((priv)->emac_ctrl_ram) | ||
| 1197 | #define EMAC_RX_BD_MEM(priv) ((priv)->emac_ctrl_ram + \ | ||
| 1198 | (((priv)->ctrl_ram_size) >> 1)) | ||
| 1199 | |||
| 1200 | /** | ||
| 1201 | * emac_init_txch: TX channel initialization | ||
| 1202 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1203 | * @ch: RX channel number | ||
| 1204 | * | ||
| 1205 | * Called during device init to setup a TX channel (allocate buffer desc | ||
| 1206 | * create free pool and keep ready for transmission | ||
| 1207 | * | ||
| 1208 | * Returns success(0) or mem alloc failures error code | ||
| 1209 | */ | ||
| 1210 | static int emac_init_txch(struct emac_priv *priv, u32 ch) | ||
| 1211 | { | ||
| 1212 | struct device *emac_dev = &priv->ndev->dev; | ||
| 1213 | u32 cnt, bd_size; | ||
| 1214 | void __iomem *mem; | ||
| 1215 | struct emac_tx_bd __iomem *curr_bd; | ||
| 1216 | struct emac_txch *txch = NULL; | ||
| 1217 | |||
| 1218 | txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL); | ||
| 1219 | if (NULL == txch) { | ||
| 1220 | dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed"); | ||
| 1221 | return -ENOMEM; | ||
| 1222 | } | ||
| 1223 | priv->txch[ch] = txch; | ||
| 1224 | txch->service_max = EMAC_DEF_TX_MAX_SERVICE; | ||
| 1225 | txch->active_queue_head = NULL; | ||
| 1226 | txch->active_queue_tail = NULL; | ||
| 1227 | txch->queue_active = 0; | ||
| 1228 | txch->teardown_pending = 0; | ||
| 1229 | |||
| 1230 | /* allocate memory for TX CPPI channel on a 4 byte boundry */ | ||
| 1231 | txch->tx_complete = kzalloc(txch->service_max * sizeof(u32), | ||
| 1232 | GFP_KERNEL); | ||
| 1233 | if (NULL == txch->tx_complete) { | ||
| 1234 | dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed"); | ||
| 1235 | kfree(txch); | ||
| 1236 | return -ENOMEM; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | /* allocate buffer descriptor pool align every BD on four word | ||
| 1240 | * boundry for future requirements */ | ||
| 1241 | bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF; | ||
| 1242 | txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; | ||
| 1243 | txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF); | ||
| 1244 | |||
| 1245 | /* alloc TX BD memory */ | ||
| 1246 | txch->bd_mem = EMAC_TX_BD_MEM(priv); | ||
| 1247 | __memzero((void __force *)txch->bd_mem, txch->alloc_size); | ||
| 1248 | |||
| 1249 | /* initialize the BD linked list */ | ||
| 1250 | mem = (void __force __iomem *) | ||
| 1251 | (((u32 __force) txch->bd_mem + 0xF) & ~0xF); | ||
| 1252 | txch->bd_pool_head = NULL; | ||
| 1253 | for (cnt = 0; cnt < txch->num_bd; cnt++) { | ||
| 1254 | curr_bd = mem + (cnt * bd_size); | ||
| 1255 | curr_bd->next = txch->bd_pool_head; | ||
| 1256 | txch->bd_pool_head = curr_bd; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | /* reset statistics counters */ | ||
| 1260 | txch->out_of_tx_bd = 0; | ||
| 1261 | txch->no_active_pkts = 0; | ||
| 1262 | txch->active_queue_count = 0; | ||
| 1263 | |||
| 1264 | return 0; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | /** | ||
| 1268 | * emac_cleanup_txch: Book-keep function to clean TX channel resources | ||
| 1269 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1270 | * @ch: TX channel number | ||
| 1271 | * | ||
| 1272 | * Called to clean up TX channel resources | ||
| 1273 | * | ||
| 1274 | */ | ||
| 1275 | static void emac_cleanup_txch(struct emac_priv *priv, u32 ch) | ||
| 1276 | { | 993 | { |
| 1277 | struct emac_txch *txch = priv->txch[ch]; | 994 | struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); |
| 1278 | 995 | if (WARN_ON(!skb)) | |
| 1279 | if (txch) { | 996 | return NULL; |
| 1280 | if (txch->bd_mem) | 997 | skb->dev = priv->ndev; |
| 1281 | txch->bd_mem = NULL; | 998 | skb_reserve(skb, NET_IP_ALIGN); |
| 1282 | kfree(txch->tx_complete); | 999 | return skb; |
| 1283 | kfree(txch); | ||
| 1284 | priv->txch[ch] = NULL; | ||
| 1285 | } | ||
| 1286 | } | 1000 | } |
| 1287 | 1001 | ||
| 1288 | /** | 1002 | static void emac_rx_handler(void *token, int len, int status) |
| 1289 | * emac_net_tx_complete: TX packet completion function | ||
| 1290 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1291 | * @net_data_tokens: packet token - skb pointer | ||
| 1292 | * @num_tokens: number of skb's to free | ||
| 1293 | * @ch: TX channel number | ||
| 1294 | * | ||
| 1295 | * Frees the skb once packet is transmitted | ||
| 1296 | * | ||
| 1297 | */ | ||
| 1298 | static int emac_net_tx_complete(struct emac_priv *priv, | ||
| 1299 | void **net_data_tokens, | ||
| 1300 | int num_tokens, u32 ch) | ||
| 1301 | { | 1003 | { |
| 1302 | struct net_device *ndev = priv->ndev; | 1004 | struct sk_buff *skb = token; |
| 1303 | u32 cnt; | 1005 | struct net_device *ndev = skb->dev; |
| 1304 | 1006 | struct emac_priv *priv = netdev_priv(ndev); | |
| 1305 | if (unlikely(num_tokens && netif_queue_stopped(ndev))) | 1007 | struct device *emac_dev = &ndev->dev; |
| 1306 | netif_start_queue(ndev); | 1008 | int ret; |
| 1307 | for (cnt = 0; cnt < num_tokens; cnt++) { | 1009 | |
| 1308 | struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt]; | 1010 | /* free and bail if we are shutting down */ |
| 1309 | if (skb == NULL) | 1011 | if (unlikely(!netif_running(ndev))) { |
| 1310 | continue; | ||
| 1311 | ndev->stats.tx_packets++; | ||
| 1312 | ndev->stats.tx_bytes += skb->len; | ||
| 1313 | dev_kfree_skb_any(skb); | 1012 | dev_kfree_skb_any(skb); |
| 1013 | return; | ||
| 1314 | } | 1014 | } |
| 1315 | return 0; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | /** | ||
| 1319 | * emac_txch_teardown: TX channel teardown | ||
| 1320 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1321 | * @ch: TX channel number | ||
| 1322 | * | ||
| 1323 | * Called to teardown TX channel | ||
| 1324 | * | ||
| 1325 | */ | ||
| 1326 | static void emac_txch_teardown(struct emac_priv *priv, u32 ch) | ||
| 1327 | { | ||
| 1328 | struct device *emac_dev = &priv->ndev->dev; | ||
| 1329 | u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ | ||
| 1330 | struct emac_txch *txch = priv->txch[ch]; | ||
| 1331 | struct emac_tx_bd __iomem *curr_bd; | ||
| 1332 | |||
| 1333 | while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) != | ||
| 1334 | EMAC_TEARDOWN_VALUE) { | ||
| 1335 | /* wait till tx teardown complete */ | ||
| 1336 | cpu_relax(); /* TODO: check if this helps ... */ | ||
| 1337 | --teardown_cnt; | ||
| 1338 | if (0 == teardown_cnt) { | ||
| 1339 | dev_err(emac_dev, "EMAC: TX teardown aborted\n"); | ||
| 1340 | break; | ||
| 1341 | } | ||
| 1342 | } | ||
| 1343 | emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE); | ||
| 1344 | |||
| 1345 | /* process sent packets and return skb's to upper layer */ | ||
| 1346 | if (1 == txch->queue_active) { | ||
| 1347 | curr_bd = txch->active_queue_head; | ||
| 1348 | while (curr_bd != NULL) { | ||
| 1349 | dma_unmap_single(emac_dev, curr_bd->buff_ptr, | ||
| 1350 | curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, | ||
| 1351 | DMA_TO_DEVICE); | ||
| 1352 | |||
| 1353 | emac_net_tx_complete(priv, (void __force *) | ||
| 1354 | &curr_bd->buf_token, 1, ch); | ||
| 1355 | if (curr_bd != txch->active_queue_tail) | ||
| 1356 | curr_bd = curr_bd->next; | ||
| 1357 | else | ||
| 1358 | break; | ||
| 1359 | } | ||
| 1360 | txch->bd_pool_head = txch->active_queue_head; | ||
| 1361 | txch->active_queue_head = | ||
| 1362 | txch->active_queue_tail = NULL; | ||
| 1363 | } | ||
| 1364 | } | ||
| 1365 | 1015 | ||
| 1366 | /** | 1016 | /* recycle on recieve error */ |
| 1367 | * emac_stop_txch: Stop TX channel operation | 1017 | if (status < 0) { |
| 1368 | * @priv: The DaVinci EMAC private adapter structure | 1018 | ndev->stats.rx_errors++; |
| 1369 | * @ch: TX channel number | 1019 | goto recycle; |
| 1370 | * | ||
| 1371 | * Called to stop TX channel operation | ||
| 1372 | * | ||
| 1373 | */ | ||
| 1374 | static void emac_stop_txch(struct emac_priv *priv, u32 ch) | ||
| 1375 | { | ||
| 1376 | struct emac_txch *txch = priv->txch[ch]; | ||
| 1377 | |||
| 1378 | if (txch) { | ||
| 1379 | txch->teardown_pending = 1; | ||
| 1380 | emac_write(EMAC_TXTEARDOWN, 0); | ||
| 1381 | emac_txch_teardown(priv, ch); | ||
| 1382 | txch->teardown_pending = 0; | ||
| 1383 | emac_write(EMAC_TXINTMASKCLEAR, BIT(ch)); | ||
| 1384 | } | 1020 | } |
| 1385 | } | ||
| 1386 | 1021 | ||
| 1387 | /** | 1022 | /* feed received packet up the stack */ |
| 1388 | * emac_tx_bdproc: TX buffer descriptor (packet) processing | 1023 | skb_put(skb, len); |
| 1389 | * @priv: The DaVinci EMAC private adapter structure | 1024 | skb->protocol = eth_type_trans(skb, ndev); |
| 1390 | * @ch: TX channel number to process buffer descriptors for | 1025 | netif_receive_skb(skb); |
| 1391 | * @budget: number of packets allowed to process | 1026 | ndev->stats.rx_bytes += len; |
| 1392 | * @pending: indication to caller that packets are pending to process | 1027 | ndev->stats.rx_packets++; |
| 1393 | * | ||
| 1394 | * Processes TX buffer descriptors after packets are transmitted - checks | ||
| 1395 | * ownership bit on the TX * descriptor and requeues it to free pool & frees | ||
| 1396 | * the SKB buffer. Only "budget" number of packets are processed and | ||
| 1397 | * indication of pending packets provided to the caller | ||
| 1398 | * | ||
| 1399 | * Returns number of packets processed | ||
| 1400 | */ | ||
| 1401 | static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) | ||
| 1402 | { | ||
| 1403 | struct device *emac_dev = &priv->ndev->dev; | ||
| 1404 | unsigned long flags; | ||
| 1405 | u32 frame_status; | ||
| 1406 | u32 pkts_processed = 0; | ||
| 1407 | u32 tx_complete_cnt = 0; | ||
| 1408 | struct emac_tx_bd __iomem *curr_bd; | ||
| 1409 | struct emac_txch *txch = priv->txch[ch]; | ||
| 1410 | u32 *tx_complete_ptr = txch->tx_complete; | ||
| 1411 | |||
| 1412 | if (unlikely(1 == txch->teardown_pending)) { | ||
| 1413 | if (netif_msg_tx_err(priv) && net_ratelimit()) { | ||
| 1414 | dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\ | ||
| 1415 | "teardown pending\n"); | ||
| 1416 | } | ||
| 1417 | return 0; /* dont handle any pkt completions */ | ||
| 1418 | } | ||
| 1419 | 1028 | ||
| 1420 | ++txch->proc_count; | 1029 | /* alloc a new packet for receive */ |
| 1421 | spin_lock_irqsave(&priv->tx_lock, flags); | 1030 | skb = emac_rx_alloc(priv); |
| 1422 | curr_bd = txch->active_queue_head; | 1031 | if (!skb) { |
| 1423 | if (NULL == curr_bd) { | 1032 | if (netif_msg_rx_err(priv) && net_ratelimit()) |
| 1424 | emac_write(EMAC_TXCP(ch), | 1033 | dev_err(emac_dev, "failed rx buffer alloc\n"); |
| 1425 | emac_virt_to_phys(txch->last_hw_bdprocessed, priv)); | 1034 | return; |
| 1426 | txch->no_active_pkts++; | ||
| 1427 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
| 1428 | return 0; | ||
| 1429 | } | 1035 | } |
| 1430 | BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); | ||
| 1431 | frame_status = curr_bd->mode; | ||
| 1432 | while ((curr_bd) && | ||
| 1433 | ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && | ||
| 1434 | (pkts_processed < budget)) { | ||
| 1435 | emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv)); | ||
| 1436 | txch->active_queue_head = curr_bd->next; | ||
| 1437 | if (frame_status & EMAC_CPPI_EOQ_BIT) { | ||
| 1438 | if (curr_bd->next) { /* misqueued packet */ | ||
| 1439 | emac_write(EMAC_TXHDP(ch), curr_bd->h_next); | ||
| 1440 | ++txch->mis_queued_packets; | ||
| 1441 | } else { | ||
| 1442 | txch->queue_active = 0; /* end of queue */ | ||
| 1443 | } | ||
| 1444 | } | ||
| 1445 | 1036 | ||
| 1446 | dma_unmap_single(emac_dev, curr_bd->buff_ptr, | 1037 | recycle: |
| 1447 | curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, | 1038 | ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, |
| 1448 | DMA_TO_DEVICE); | 1039 | skb_tailroom(skb), GFP_KERNEL); |
| 1449 | 1040 | if (WARN_ON(ret < 0)) | |
| 1450 | *tx_complete_ptr = (u32) curr_bd->buf_token; | 1041 | dev_kfree_skb_any(skb); |
| 1451 | ++tx_complete_ptr; | ||
| 1452 | ++tx_complete_cnt; | ||
| 1453 | curr_bd->next = txch->bd_pool_head; | ||
| 1454 | txch->bd_pool_head = curr_bd; | ||
| 1455 | --txch->active_queue_count; | ||
| 1456 | pkts_processed++; | ||
| 1457 | txch->last_hw_bdprocessed = curr_bd; | ||
| 1458 | curr_bd = txch->active_queue_head; | ||
| 1459 | if (curr_bd) { | ||
| 1460 | BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); | ||
| 1461 | frame_status = curr_bd->mode; | ||
| 1462 | } | ||
| 1463 | } /* end of pkt processing loop */ | ||
| 1464 | |||
| 1465 | emac_net_tx_complete(priv, | ||
| 1466 | (void *)&txch->tx_complete[0], | ||
| 1467 | tx_complete_cnt, ch); | ||
| 1468 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
| 1469 | return pkts_processed; | ||
| 1470 | } | 1042 | } |
| 1471 | 1043 | ||
| 1472 | #define EMAC_ERR_TX_OUT_OF_BD -1 | 1044 | static void emac_tx_handler(void *token, int len, int status) |
| 1473 | |||
| 1474 | /** | ||
| 1475 | * emac_send: EMAC Transmit function (internal) | ||
| 1476 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1477 | * @pkt: packet pointer (contains skb ptr) | ||
| 1478 | * @ch: TX channel number | ||
| 1479 | * | ||
| 1480 | * Called by the transmit function to queue the packet in EMAC hardware queue | ||
| 1481 | * | ||
| 1482 | * Returns success(0) or error code (typically out of desc's) | ||
| 1483 | */ | ||
| 1484 | static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) | ||
| 1485 | { | 1045 | { |
| 1486 | unsigned long flags; | 1046 | struct sk_buff *skb = token; |
| 1487 | struct emac_tx_bd __iomem *curr_bd; | 1047 | struct net_device *ndev = skb->dev; |
| 1488 | struct emac_txch *txch; | ||
| 1489 | struct emac_netbufobj *buf_list; | ||
| 1490 | |||
| 1491 | txch = priv->txch[ch]; | ||
| 1492 | buf_list = pkt->buf_list; /* get handle to the buffer array */ | ||
| 1493 | |||
| 1494 | /* check packet size and pad if short */ | ||
| 1495 | if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) { | ||
| 1496 | buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length); | ||
| 1497 | pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE; | ||
| 1498 | } | ||
| 1499 | 1048 | ||
| 1500 | spin_lock_irqsave(&priv->tx_lock, flags); | 1049 | if (unlikely(netif_queue_stopped(ndev))) |
| 1501 | curr_bd = txch->bd_pool_head; | 1050 | netif_start_queue(ndev); |
| 1502 | if (curr_bd == NULL) { | 1051 | ndev->stats.tx_packets++; |
| 1503 | txch->out_of_tx_bd++; | 1052 | ndev->stats.tx_bytes += len; |
| 1504 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1053 | dev_kfree_skb_any(skb); |
| 1505 | return EMAC_ERR_TX_OUT_OF_BD; | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | txch->bd_pool_head = curr_bd->next; | ||
| 1509 | curr_bd->buf_token = buf_list->buf_token; | ||
| 1510 | curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr, | ||
| 1511 | buf_list->length, DMA_TO_DEVICE); | ||
| 1512 | curr_bd->off_b_len = buf_list->length; | ||
| 1513 | curr_bd->h_next = 0; | ||
| 1514 | curr_bd->next = NULL; | ||
| 1515 | curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | | ||
| 1516 | EMAC_CPPI_EOP_BIT | pkt->pkt_length); | ||
| 1517 | |||
| 1518 | /* flush the packet from cache if write back cache is present */ | ||
| 1519 | BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); | ||
| 1520 | |||
| 1521 | /* send the packet */ | ||
| 1522 | if (txch->active_queue_head == NULL) { | ||
| 1523 | txch->active_queue_head = curr_bd; | ||
| 1524 | txch->active_queue_tail = curr_bd; | ||
| 1525 | if (1 != txch->queue_active) { | ||
| 1526 | emac_write(EMAC_TXHDP(ch), | ||
| 1527 | emac_virt_to_phys(curr_bd, priv)); | ||
| 1528 | txch->queue_active = 1; | ||
| 1529 | } | ||
| 1530 | ++txch->queue_reinit; | ||
| 1531 | } else { | ||
| 1532 | register struct emac_tx_bd __iomem *tail_bd; | ||
| 1533 | register u32 frame_status; | ||
| 1534 | |||
| 1535 | tail_bd = txch->active_queue_tail; | ||
| 1536 | tail_bd->next = curr_bd; | ||
| 1537 | txch->active_queue_tail = curr_bd; | ||
| 1538 | tail_bd = EMAC_VIRT_NOCACHE(tail_bd); | ||
| 1539 | tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv); | ||
| 1540 | frame_status = tail_bd->mode; | ||
| 1541 | if (frame_status & EMAC_CPPI_EOQ_BIT) { | ||
| 1542 | emac_write(EMAC_TXHDP(ch), | ||
| 1543 | emac_virt_to_phys(curr_bd, priv)); | ||
| 1544 | frame_status &= ~(EMAC_CPPI_EOQ_BIT); | ||
| 1545 | tail_bd->mode = frame_status; | ||
| 1546 | ++txch->end_of_queue_add; | ||
| 1547 | } | ||
| 1548 | } | ||
| 1549 | txch->active_queue_count++; | ||
| 1550 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
| 1551 | return 0; | ||
| 1552 | } | 1054 | } |
| 1553 | 1055 | ||
| 1554 | /** | 1056 | /** |
| @@ -1565,42 +1067,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
| 1565 | { | 1067 | { |
| 1566 | struct device *emac_dev = &ndev->dev; | 1068 | struct device *emac_dev = &ndev->dev; |
| 1567 | int ret_code; | 1069 | int ret_code; |
| 1568 | struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */ | ||
| 1569 | struct emac_netpktobj tx_packet; /* packet object */ | ||
| 1570 | struct emac_priv *priv = netdev_priv(ndev); | 1070 | struct emac_priv *priv = netdev_priv(ndev); |
| 1571 | 1071 | ||
| 1572 | /* If no link, return */ | 1072 | /* If no link, return */ |
| 1573 | if (unlikely(!priv->link)) { | 1073 | if (unlikely(!priv->link)) { |
| 1574 | if (netif_msg_tx_err(priv) && net_ratelimit()) | 1074 | if (netif_msg_tx_err(priv) && net_ratelimit()) |
| 1575 | dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); | 1075 | dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); |
| 1576 | return NETDEV_TX_BUSY; | 1076 | goto fail_tx; |
| 1077 | } | ||
| 1078 | |||
| 1079 | ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE); | ||
| 1080 | if (unlikely(ret_code < 0)) { | ||
| 1081 | if (netif_msg_tx_err(priv) && net_ratelimit()) | ||
| 1082 | dev_err(emac_dev, "DaVinci EMAC: packet pad failed"); | ||
| 1083 | goto fail_tx; | ||
| 1577 | } | 1084 | } |
| 1578 | 1085 | ||
| 1579 | /* Build the buffer and packet objects - Since only single fragment is | 1086 | ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, |
| 1580 | * supported, need not set length and token in both packet & object. | 1087 | GFP_KERNEL); |
| 1581 | * Doing so for completeness sake & to show that this needs to be done | ||
| 1582 | * in multifragment case | ||
| 1583 | */ | ||
| 1584 | tx_packet.buf_list = &tx_buf; | ||
| 1585 | tx_packet.num_bufs = 1; /* only single fragment supported */ | ||
| 1586 | tx_packet.pkt_length = skb->len; | ||
| 1587 | tx_packet.pkt_token = (void *)skb; | ||
| 1588 | tx_buf.length = skb->len; | ||
| 1589 | tx_buf.buf_token = (void *)skb; | ||
| 1590 | tx_buf.data_ptr = skb->data; | ||
| 1591 | ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); | ||
| 1592 | if (unlikely(ret_code != 0)) { | 1088 | if (unlikely(ret_code != 0)) { |
| 1593 | if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { | 1089 | if (netif_msg_tx_err(priv) && net_ratelimit()) |
| 1594 | if (netif_msg_tx_err(priv) && net_ratelimit()) | 1090 | dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); |
| 1595 | dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\ | 1091 | goto fail_tx; |
| 1596 | " err. Out of TX BD's"); | ||
| 1597 | netif_stop_queue(priv->ndev); | ||
| 1598 | } | ||
| 1599 | ndev->stats.tx_dropped++; | ||
| 1600 | return NETDEV_TX_BUSY; | ||
| 1601 | } | 1092 | } |
| 1602 | 1093 | ||
| 1603 | return NETDEV_TX_OK; | 1094 | return NETDEV_TX_OK; |
| 1095 | |||
| 1096 | fail_tx: | ||
| 1097 | ndev->stats.tx_dropped++; | ||
| 1098 | netif_stop_queue(ndev); | ||
| 1099 | return NETDEV_TX_BUSY; | ||
| 1604 | } | 1100 | } |
| 1605 | 1101 | ||
| 1606 | /** | 1102 | /** |
| @@ -1621,218 +1117,16 @@ static void emac_dev_tx_timeout(struct net_device *ndev) | |||
| 1621 | if (netif_msg_tx_err(priv)) | 1117 | if (netif_msg_tx_err(priv)) |
| 1622 | dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); | 1118 | dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); |
| 1623 | 1119 | ||
| 1120 | emac_dump_regs(priv); | ||
| 1121 | |||
| 1624 | ndev->stats.tx_errors++; | 1122 | ndev->stats.tx_errors++; |
| 1625 | emac_int_disable(priv); | 1123 | emac_int_disable(priv); |
| 1626 | emac_stop_txch(priv, EMAC_DEF_TX_CH); | 1124 | cpdma_chan_stop(priv->txchan); |
| 1627 | emac_cleanup_txch(priv, EMAC_DEF_TX_CH); | 1125 | cpdma_chan_start(priv->txchan); |
| 1628 | emac_init_txch(priv, EMAC_DEF_TX_CH); | ||
| 1629 | emac_write(EMAC_TXHDP(0), 0); | ||
| 1630 | emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH)); | ||
| 1631 | emac_int_enable(priv); | 1126 | emac_int_enable(priv); |
| 1632 | } | 1127 | } |
| 1633 | 1128 | ||
| 1634 | /** | 1129 | /** |
| 1635 | * emac_net_alloc_rx_buf: Allocate a skb for RX | ||
| 1636 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1637 | * @buf_size: size of SKB data buffer to allocate | ||
| 1638 | * @data_token: data token returned (skb handle for storing in buffer desc) | ||
| 1639 | * @ch: RX channel number | ||
| 1640 | * | ||
| 1641 | * Called during RX channel setup - allocates skb buffer of required size | ||
| 1642 | * and provides the skb handle and allocated buffer data pointer to caller | ||
| 1643 | * | ||
| 1644 | * Returns skb data pointer or 0 on failure to alloc skb | ||
| 1645 | */ | ||
| 1646 | static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size, | ||
| 1647 | void **data_token, u32 ch) | ||
| 1648 | { | ||
| 1649 | struct net_device *ndev = priv->ndev; | ||
| 1650 | struct device *emac_dev = &ndev->dev; | ||
| 1651 | struct sk_buff *p_skb; | ||
| 1652 | |||
| 1653 | p_skb = dev_alloc_skb(buf_size); | ||
| 1654 | if (unlikely(NULL == p_skb)) { | ||
| 1655 | if (netif_msg_rx_err(priv) && net_ratelimit()) | ||
| 1656 | dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb"); | ||
| 1657 | return NULL; | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | /* set device pointer in skb and reserve space for extra bytes */ | ||
| 1661 | p_skb->dev = ndev; | ||
| 1662 | skb_reserve(p_skb, NET_IP_ALIGN); | ||
| 1663 | *data_token = (void *) p_skb; | ||
| 1664 | return p_skb->data; | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | /** | ||
| 1668 | * emac_init_rxch: RX channel initialization | ||
| 1669 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1670 | * @ch: RX channel number | ||
| 1671 | * @param: mac address for RX channel | ||
| 1672 | * | ||
| 1673 | * Called during device init to setup a RX channel (allocate buffers and | ||
| 1674 | * buffer descriptors, create queue and keep ready for reception | ||
| 1675 | * | ||
| 1676 | * Returns success(0) or mem alloc failures error code | ||
| 1677 | */ | ||
| 1678 | static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) | ||
| 1679 | { | ||
| 1680 | struct device *emac_dev = &priv->ndev->dev; | ||
| 1681 | u32 cnt, bd_size; | ||
| 1682 | void __iomem *mem; | ||
| 1683 | struct emac_rx_bd __iomem *curr_bd; | ||
| 1684 | struct emac_rxch *rxch = NULL; | ||
| 1685 | |||
| 1686 | rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL); | ||
| 1687 | if (NULL == rxch) { | ||
| 1688 | dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed"); | ||
| 1689 | return -ENOMEM; | ||
| 1690 | } | ||
| 1691 | priv->rxch[ch] = rxch; | ||
| 1692 | rxch->buf_size = priv->rx_buf_size; | ||
| 1693 | rxch->service_max = EMAC_DEF_RX_MAX_SERVICE; | ||
| 1694 | rxch->queue_active = 0; | ||
| 1695 | rxch->teardown_pending = 0; | ||
| 1696 | |||
| 1697 | /* save mac address */ | ||
| 1698 | for (cnt = 0; cnt < 6; cnt++) | ||
| 1699 | rxch->mac_addr[cnt] = param[cnt]; | ||
| 1700 | |||
| 1701 | /* allocate buffer descriptor pool align every BD on four word | ||
| 1702 | * boundry for future requirements */ | ||
| 1703 | bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF; | ||
| 1704 | rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; | ||
| 1705 | rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF); | ||
| 1706 | rxch->bd_mem = EMAC_RX_BD_MEM(priv); | ||
| 1707 | __memzero((void __force *)rxch->bd_mem, rxch->alloc_size); | ||
| 1708 | rxch->pkt_queue.buf_list = &rxch->buf_queue; | ||
| 1709 | |||
| 1710 | /* allocate RX buffer and initialize the BD linked list */ | ||
| 1711 | mem = (void __force __iomem *) | ||
| 1712 | (((u32 __force) rxch->bd_mem + 0xF) & ~0xF); | ||
| 1713 | rxch->active_queue_head = NULL; | ||
| 1714 | rxch->active_queue_tail = mem; | ||
| 1715 | for (cnt = 0; cnt < rxch->num_bd; cnt++) { | ||
| 1716 | curr_bd = mem + (cnt * bd_size); | ||
| 1717 | /* for future use the last parameter contains the BD ptr */ | ||
| 1718 | curr_bd->data_ptr = emac_net_alloc_rx_buf(priv, | ||
| 1719 | rxch->buf_size, | ||
| 1720 | (void __force **)&curr_bd->buf_token, | ||
| 1721 | EMAC_DEF_RX_CH); | ||
| 1722 | if (curr_bd->data_ptr == NULL) { | ||
| 1723 | dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \ | ||
| 1724 | "failed for ch %d\n", ch); | ||
| 1725 | kfree(rxch); | ||
| 1726 | return -ENOMEM; | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | /* populate the hardware descriptor */ | ||
| 1730 | curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head, | ||
| 1731 | priv); | ||
| 1732 | curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr, | ||
| 1733 | rxch->buf_size, DMA_FROM_DEVICE); | ||
| 1734 | curr_bd->off_b_len = rxch->buf_size; | ||
| 1735 | curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; | ||
| 1736 | |||
| 1737 | /* write back to hardware memory */ | ||
| 1738 | BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd, | ||
| 1739 | EMAC_BD_LENGTH_FOR_CACHE); | ||
| 1740 | curr_bd->next = rxch->active_queue_head; | ||
| 1741 | rxch->active_queue_head = curr_bd; | ||
| 1742 | } | ||
| 1743 | |||
| 1744 | /* At this point rxCppi->activeQueueHead points to the first | ||
| 1745 | RX BD ready to be given to RX HDP and rxch->active_queue_tail | ||
| 1746 | points to the last RX BD | ||
| 1747 | */ | ||
| 1748 | return 0; | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | /** | ||
| 1752 | * emac_rxch_teardown: RX channel teardown | ||
| 1753 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1754 | * @ch: RX channel number | ||
| 1755 | * | ||
| 1756 | * Called during device stop to teardown RX channel | ||
| 1757 | * | ||
| 1758 | */ | ||
| 1759 | static void emac_rxch_teardown(struct emac_priv *priv, u32 ch) | ||
| 1760 | { | ||
| 1761 | struct device *emac_dev = &priv->ndev->dev; | ||
| 1762 | u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ | ||
| 1763 | |||
| 1764 | while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) != | ||
| 1765 | EMAC_TEARDOWN_VALUE) { | ||
| 1766 | /* wait till tx teardown complete */ | ||
| 1767 | cpu_relax(); /* TODO: check if this helps ... */ | ||
| 1768 | --teardown_cnt; | ||
| 1769 | if (0 == teardown_cnt) { | ||
| 1770 | dev_err(emac_dev, "EMAC: RX teardown aborted\n"); | ||
| 1771 | break; | ||
| 1772 | } | ||
| 1773 | } | ||
| 1774 | emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE); | ||
| 1775 | } | ||
| 1776 | |||
| 1777 | /** | ||
| 1778 | * emac_stop_rxch: Stop RX channel operation | ||
| 1779 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1780 | * @ch: RX channel number | ||
| 1781 | * | ||
| 1782 | * Called during device stop to stop RX channel operation | ||
| 1783 | * | ||
| 1784 | */ | ||
| 1785 | static void emac_stop_rxch(struct emac_priv *priv, u32 ch) | ||
| 1786 | { | ||
| 1787 | struct emac_rxch *rxch = priv->rxch[ch]; | ||
| 1788 | |||
| 1789 | if (rxch) { | ||
| 1790 | rxch->teardown_pending = 1; | ||
| 1791 | emac_write(EMAC_RXTEARDOWN, ch); | ||
| 1792 | /* wait for teardown complete */ | ||
| 1793 | emac_rxch_teardown(priv, ch); | ||
| 1794 | rxch->teardown_pending = 0; | ||
| 1795 | emac_write(EMAC_RXINTMASKCLEAR, BIT(ch)); | ||
| 1796 | } | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | /** | ||
| 1800 | * emac_cleanup_rxch: Book-keep function to clean RX channel resources | ||
| 1801 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1802 | * @ch: RX channel number | ||
| 1803 | * | ||
| 1804 | * Called during device stop to clean up RX channel resources | ||
| 1805 | * | ||
| 1806 | */ | ||
| 1807 | static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch) | ||
| 1808 | { | ||
| 1809 | struct emac_rxch *rxch = priv->rxch[ch]; | ||
| 1810 | struct emac_rx_bd __iomem *curr_bd; | ||
| 1811 | |||
| 1812 | if (rxch) { | ||
| 1813 | /* free the receive buffers previously allocated */ | ||
| 1814 | curr_bd = rxch->active_queue_head; | ||
| 1815 | while (curr_bd) { | ||
| 1816 | if (curr_bd->buf_token) { | ||
| 1817 | dma_unmap_single(&priv->ndev->dev, | ||
| 1818 | curr_bd->buff_ptr, | ||
| 1819 | curr_bd->off_b_len | ||
| 1820 | & EMAC_RX_BD_BUF_SIZE, | ||
| 1821 | DMA_FROM_DEVICE); | ||
| 1822 | |||
| 1823 | dev_kfree_skb_any((struct sk_buff *)\ | ||
| 1824 | curr_bd->buf_token); | ||
| 1825 | } | ||
| 1826 | curr_bd = curr_bd->next; | ||
| 1827 | } | ||
| 1828 | if (rxch->bd_mem) | ||
| 1829 | rxch->bd_mem = NULL; | ||
| 1830 | kfree(rxch); | ||
| 1831 | priv->rxch[ch] = NULL; | ||
| 1832 | } | ||
| 1833 | } | ||
| 1834 | |||
| 1835 | /** | ||
| 1836 | * emac_set_type0addr: Set EMAC Type0 mac address | 1130 | * emac_set_type0addr: Set EMAC Type0 mac address |
| 1837 | * @priv: The DaVinci EMAC private adapter structure | 1131 | * @priv: The DaVinci EMAC private adapter structure |
| 1838 | * @ch: RX channel number | 1132 | * @ch: RX channel number |
| @@ -1948,7 +1242,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) | |||
| 1948 | static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) | 1242 | static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) |
| 1949 | { | 1243 | { |
| 1950 | struct emac_priv *priv = netdev_priv(ndev); | 1244 | struct emac_priv *priv = netdev_priv(ndev); |
| 1951 | struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH]; | ||
| 1952 | struct device *emac_dev = &priv->ndev->dev; | 1245 | struct device *emac_dev = &priv->ndev->dev; |
| 1953 | struct sockaddr *sa = addr; | 1246 | struct sockaddr *sa = addr; |
| 1954 | 1247 | ||
| @@ -1959,11 +1252,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) | |||
| 1959 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); | 1252 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); |
| 1960 | memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); | 1253 | memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); |
| 1961 | 1254 | ||
| 1962 | /* If the interface is down - rxch is NULL. */ | ||
| 1963 | /* MAC address is configured only after the interface is enabled. */ | 1255 | /* MAC address is configured only after the interface is enabled. */ |
| 1964 | if (netif_running(ndev)) { | 1256 | if (netif_running(ndev)) { |
| 1965 | memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); | 1257 | memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); |
| 1966 | emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); | 1258 | emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); |
| 1967 | } | 1259 | } |
| 1968 | 1260 | ||
| 1969 | if (netif_msg_drv(priv)) | 1261 | if (netif_msg_drv(priv)) |
| @@ -1974,194 +1266,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) | |||
| 1974 | } | 1266 | } |
| 1975 | 1267 | ||
| 1976 | /** | 1268 | /** |
| 1977 | * emac_addbd_to_rx_queue: Recycle RX buffer descriptor | ||
| 1978 | * @priv: The DaVinci EMAC private adapter structure | ||
| 1979 | * @ch: RX channel number to process buffer descriptors for | ||
| 1980 | * @curr_bd: current buffer descriptor | ||
| 1981 | * @buffer: buffer pointer for descriptor | ||
| 1982 | * @buf_token: buffer token (stores skb information) | ||
| 1983 | * | ||
| 1984 | * Prepares the recycled buffer descriptor and addes it to hardware | ||
| 1985 | * receive queue - if queue empty this descriptor becomes the head | ||
| 1986 | * else addes the descriptor to end of queue | ||
| 1987 | * | ||
| 1988 | */ | ||
| 1989 | static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, | ||
| 1990 | struct emac_rx_bd __iomem *curr_bd, | ||
| 1991 | char *buffer, void *buf_token) | ||
| 1992 | { | ||
| 1993 | struct emac_rxch *rxch = priv->rxch[ch]; | ||
| 1994 | |||
| 1995 | /* populate the hardware descriptor */ | ||
| 1996 | curr_bd->h_next = 0; | ||
| 1997 | curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer, | ||
| 1998 | rxch->buf_size, DMA_FROM_DEVICE); | ||
| 1999 | curr_bd->off_b_len = rxch->buf_size; | ||
| 2000 | curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; | ||
| 2001 | curr_bd->next = NULL; | ||
| 2002 | curr_bd->data_ptr = buffer; | ||
| 2003 | curr_bd->buf_token = buf_token; | ||
| 2004 | |||
| 2005 | /* write back */ | ||
| 2006 | BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); | ||
| 2007 | if (rxch->active_queue_head == NULL) { | ||
| 2008 | rxch->active_queue_head = curr_bd; | ||
| 2009 | rxch->active_queue_tail = curr_bd; | ||
| 2010 | if (0 != rxch->queue_active) { | ||
| 2011 | emac_write(EMAC_RXHDP(ch), | ||
| 2012 | emac_virt_to_phys(rxch->active_queue_head, priv)); | ||
| 2013 | rxch->queue_active = 1; | ||
| 2014 | } | ||
| 2015 | } else { | ||
| 2016 | struct emac_rx_bd __iomem *tail_bd; | ||
| 2017 | u32 frame_status; | ||
| 2018 | |||
| 2019 | tail_bd = rxch->active_queue_tail; | ||
| 2020 | rxch->active_queue_tail = curr_bd; | ||
| 2021 | tail_bd->next = curr_bd; | ||
| 2022 | tail_bd = EMAC_VIRT_NOCACHE(tail_bd); | ||
| 2023 | tail_bd->h_next = emac_virt_to_phys(curr_bd, priv); | ||
| 2024 | frame_status = tail_bd->mode; | ||
| 2025 | if (frame_status & EMAC_CPPI_EOQ_BIT) { | ||
| 2026 | emac_write(EMAC_RXHDP(ch), | ||
| 2027 | emac_virt_to_phys(curr_bd, priv)); | ||
| 2028 | frame_status &= ~(EMAC_CPPI_EOQ_BIT); | ||
| 2029 | tail_bd->mode = frame_status; | ||
| 2030 | ++rxch->end_of_queue_add; | ||
| 2031 | } | ||
| 2032 | } | ||
| 2033 | ++rxch->recycled_bd; | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | /** | ||
| 2037 | * emac_net_rx_cb: Prepares packet and sends to upper layer | ||
| 2038 | * @priv: The DaVinci EMAC private adapter structure | ||
| 2039 | * @net_pkt_list: Network packet list (received packets) | ||
| 2040 | * | ||
| 2041 | * Invalidates packet buffer memory and sends the received packet to upper | ||
| 2042 | * layer | ||
| 2043 | * | ||
| 2044 | * Returns success or appropriate error code (none as of now) | ||
| 2045 | */ | ||
| 2046 | static int emac_net_rx_cb(struct emac_priv *priv, | ||
| 2047 | struct emac_netpktobj *net_pkt_list) | ||
| 2048 | { | ||
| 2049 | struct net_device *ndev = priv->ndev; | ||
| 2050 | struct sk_buff *p_skb = net_pkt_list->pkt_token; | ||
| 2051 | /* set length of packet */ | ||
| 2052 | skb_put(p_skb, net_pkt_list->pkt_length); | ||
| 2053 | p_skb->protocol = eth_type_trans(p_skb, priv->ndev); | ||
| 2054 | netif_receive_skb(p_skb); | ||
| 2055 | ndev->stats.rx_bytes += net_pkt_list->pkt_length; | ||
| 2056 | ndev->stats.rx_packets++; | ||
| 2057 | return 0; | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | /** | ||
| 2061 | * emac_rx_bdproc: RX buffer descriptor (packet) processing | ||
| 2062 | * @priv: The DaVinci EMAC private adapter structure | ||
| 2063 | * @ch: RX channel number to process buffer descriptors for | ||
| 2064 | * @budget: number of packets allowed to process | ||
| 2065 | * @pending: indication to caller that packets are pending to process | ||
| 2066 | * | ||
| 2067 | * Processes RX buffer descriptors - checks ownership bit on the RX buffer | ||
| 2068 | * descriptor, sends the receive packet to upper layer, allocates a new SKB | ||
| 2069 | * and recycles the buffer descriptor (requeues it in hardware RX queue). | ||
| 2070 | * Only "budget" number of packets are processed and indication of pending | ||
| 2071 | * packets provided to the caller. | ||
| 2072 | * | ||
| 2073 | * Returns number of packets processed (and indication of pending packets) | ||
| 2074 | */ | ||
| 2075 | static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) | ||
| 2076 | { | ||
| 2077 | unsigned long flags; | ||
| 2078 | u32 frame_status; | ||
| 2079 | u32 pkts_processed = 0; | ||
| 2080 | char *new_buffer; | ||
| 2081 | struct emac_rx_bd __iomem *curr_bd; | ||
| 2082 | struct emac_rx_bd __iomem *last_bd; | ||
| 2083 | struct emac_netpktobj *curr_pkt, pkt_obj; | ||
| 2084 | struct emac_netbufobj buf_obj; | ||
| 2085 | struct emac_netbufobj *rx_buf_obj; | ||
| 2086 | void *new_buf_token; | ||
| 2087 | struct emac_rxch *rxch = priv->rxch[ch]; | ||
| 2088 | |||
| 2089 | if (unlikely(1 == rxch->teardown_pending)) | ||
| 2090 | return 0; | ||
| 2091 | ++rxch->proc_count; | ||
| 2092 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
| 2093 | pkt_obj.buf_list = &buf_obj; | ||
| 2094 | curr_pkt = &pkt_obj; | ||
| 2095 | curr_bd = rxch->active_queue_head; | ||
| 2096 | BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); | ||
| 2097 | frame_status = curr_bd->mode; | ||
| 2098 | |||
| 2099 | while ((curr_bd) && | ||
| 2100 | ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && | ||
| 2101 | (pkts_processed < budget)) { | ||
| 2102 | |||
| 2103 | new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size, | ||
| 2104 | &new_buf_token, EMAC_DEF_RX_CH); | ||
| 2105 | if (unlikely(NULL == new_buffer)) { | ||
| 2106 | ++rxch->out_of_rx_buffers; | ||
| 2107 | goto end_emac_rx_bdproc; | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | /* populate received packet data structure */ | ||
| 2111 | rx_buf_obj = &curr_pkt->buf_list[0]; | ||
| 2112 | rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr; | ||
| 2113 | rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE; | ||
| 2114 | rx_buf_obj->buf_token = curr_bd->buf_token; | ||
| 2115 | |||
| 2116 | dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr, | ||
| 2117 | curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, | ||
| 2118 | DMA_FROM_DEVICE); | ||
| 2119 | |||
| 2120 | curr_pkt->pkt_token = curr_pkt->buf_list->buf_token; | ||
| 2121 | curr_pkt->num_bufs = 1; | ||
| 2122 | curr_pkt->pkt_length = | ||
| 2123 | (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); | ||
| 2124 | emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv)); | ||
| 2125 | ++rxch->processed_bd; | ||
| 2126 | last_bd = curr_bd; | ||
| 2127 | curr_bd = last_bd->next; | ||
| 2128 | rxch->active_queue_head = curr_bd; | ||
| 2129 | |||
| 2130 | /* check if end of RX queue ? */ | ||
| 2131 | if (frame_status & EMAC_CPPI_EOQ_BIT) { | ||
| 2132 | if (curr_bd) { | ||
| 2133 | ++rxch->mis_queued_packets; | ||
| 2134 | emac_write(EMAC_RXHDP(ch), | ||
| 2135 | emac_virt_to_phys(curr_bd, priv)); | ||
| 2136 | } else { | ||
| 2137 | ++rxch->end_of_queue; | ||
| 2138 | rxch->queue_active = 0; | ||
| 2139 | } | ||
| 2140 | } | ||
| 2141 | |||
| 2142 | /* recycle BD */ | ||
| 2143 | emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer, | ||
| 2144 | new_buf_token); | ||
| 2145 | |||
| 2146 | /* return the packet to the user - BD ptr passed in | ||
| 2147 | * last parameter for potential *future* use */ | ||
| 2148 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
| 2149 | emac_net_rx_cb(priv, curr_pkt); | ||
| 2150 | spin_lock_irqsave(&priv->rx_lock, flags); | ||
| 2151 | curr_bd = rxch->active_queue_head; | ||
| 2152 | if (curr_bd) { | ||
| 2153 | BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); | ||
| 2154 | frame_status = curr_bd->mode; | ||
| 2155 | } | ||
| 2156 | ++pkts_processed; | ||
| 2157 | } | ||
| 2158 | |||
| 2159 | end_emac_rx_bdproc: | ||
| 2160 | spin_unlock_irqrestore(&priv->rx_lock, flags); | ||
| 2161 | return pkts_processed; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | /** | ||
| 2165 | * emac_hw_enable: Enable EMAC hardware for packet transmission/reception | 1269 | * emac_hw_enable: Enable EMAC hardware for packet transmission/reception |
| 2166 | * @priv: The DaVinci EMAC private adapter structure | 1270 | * @priv: The DaVinci EMAC private adapter structure |
| 2167 | * | 1271 | * |
| @@ -2172,7 +1276,7 @@ end_emac_rx_bdproc: | |||
| 2172 | */ | 1276 | */ |
| 2173 | static int emac_hw_enable(struct emac_priv *priv) | 1277 | static int emac_hw_enable(struct emac_priv *priv) |
| 2174 | { | 1278 | { |
| 2175 | u32 ch, val, mbp_enable, mac_control; | 1279 | u32 val, mbp_enable, mac_control; |
| 2176 | 1280 | ||
| 2177 | /* Soft reset */ | 1281 | /* Soft reset */ |
| 2178 | emac_write(EMAC_SOFTRESET, 1); | 1282 | emac_write(EMAC_SOFTRESET, 1); |
| @@ -2215,26 +1319,9 @@ static int emac_hw_enable(struct emac_priv *priv) | |||
| 2215 | emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); | 1319 | emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); |
| 2216 | priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; | 1320 | priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; |
| 2217 | 1321 | ||
| 2218 | val = emac_read(EMAC_TXCONTROL); | ||
| 2219 | val |= EMAC_TX_CONTROL_TX_ENABLE_VAL; | ||
| 2220 | emac_write(EMAC_TXCONTROL, val); | ||
| 2221 | val = emac_read(EMAC_RXCONTROL); | ||
| 2222 | val |= EMAC_RX_CONTROL_RX_ENABLE_VAL; | ||
| 2223 | emac_write(EMAC_RXCONTROL, val); | ||
| 2224 | emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); | 1322 | emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); |
| 2225 | 1323 | ||
| 2226 | for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) { | 1324 | emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); |
| 2227 | emac_write(EMAC_TXHDP(ch), 0); | ||
| 2228 | emac_write(EMAC_TXINTMASKSET, BIT(ch)); | ||
| 2229 | } | ||
| 2230 | for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) { | ||
| 2231 | struct emac_rxch *rxch = priv->rxch[ch]; | ||
| 2232 | emac_setmac(priv, ch, rxch->mac_addr); | ||
| 2233 | emac_write(EMAC_RXINTMASKSET, BIT(ch)); | ||
| 2234 | rxch->queue_active = 1; | ||
| 2235 | emac_write(EMAC_RXHDP(ch), | ||
| 2236 | emac_virt_to_phys(rxch->active_queue_head, priv)); | ||
| 2237 | } | ||
| 2238 | 1325 | ||
| 2239 | /* Enable MII */ | 1326 | /* Enable MII */ |
| 2240 | val = emac_read(EMAC_MACCONTROL); | 1327 | val = emac_read(EMAC_MACCONTROL); |
| @@ -2279,8 +1366,8 @@ static int emac_poll(struct napi_struct *napi, int budget) | |||
| 2279 | mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; | 1366 | mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; |
| 2280 | 1367 | ||
| 2281 | if (status & mask) { | 1368 | if (status & mask) { |
| 2282 | num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, | 1369 | num_tx_pkts = cpdma_chan_process(priv->txchan, |
| 2283 | EMAC_DEF_TX_MAX_SERVICE); | 1370 | EMAC_DEF_TX_MAX_SERVICE); |
| 2284 | } /* TX processing */ | 1371 | } /* TX processing */ |
| 2285 | 1372 | ||
| 2286 | mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; | 1373 | mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; |
| @@ -2289,7 +1376,7 @@ static int emac_poll(struct napi_struct *napi, int budget) | |||
| 2289 | mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; | 1376 | mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; |
| 2290 | 1377 | ||
| 2291 | if (status & mask) { | 1378 | if (status & mask) { |
| 2292 | num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); | 1379 | num_rx_pkts = cpdma_chan_process(priv->rxchan, budget); |
| 2293 | } /* RX processing */ | 1380 | } /* RX processing */ |
| 2294 | 1381 | ||
| 2295 | mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; | 1382 | mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; |
| @@ -2348,79 +1435,6 @@ void emac_poll_controller(struct net_device *ndev) | |||
| 2348 | } | 1435 | } |
| 2349 | #endif | 1436 | #endif |
| 2350 | 1437 | ||
| 2351 | /* PHY/MII bus related */ | ||
| 2352 | |||
| 2353 | /* Wait until mdio is ready for next command */ | ||
| 2354 | #define MDIO_WAIT_FOR_USER_ACCESS\ | ||
| 2355 | while ((emac_mdio_read((MDIO_USERACCESS(0))) &\ | ||
| 2356 | MDIO_USERACCESS_GO) != 0) | ||
| 2357 | |||
| 2358 | static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg) | ||
| 2359 | { | ||
| 2360 | unsigned int phy_data = 0; | ||
| 2361 | unsigned int phy_control; | ||
| 2362 | |||
| 2363 | /* Wait until mdio is ready for next command */ | ||
| 2364 | MDIO_WAIT_FOR_USER_ACCESS; | ||
| 2365 | |||
| 2366 | phy_control = (MDIO_USERACCESS_GO | | ||
| 2367 | MDIO_USERACCESS_READ | | ||
| 2368 | ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | | ||
| 2369 | ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | | ||
| 2370 | (phy_data & MDIO_USERACCESS_DATA)); | ||
| 2371 | emac_mdio_write(MDIO_USERACCESS(0), phy_control); | ||
| 2372 | |||
| 2373 | /* Wait until mdio is ready for next command */ | ||
| 2374 | MDIO_WAIT_FOR_USER_ACCESS; | ||
| 2375 | |||
| 2376 | return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA; | ||
| 2377 | |||
| 2378 | } | ||
| 2379 | |||
| 2380 | static int emac_mii_write(struct mii_bus *bus, int phy_id, | ||
| 2381 | int phy_reg, u16 phy_data) | ||
| 2382 | { | ||
| 2383 | |||
| 2384 | unsigned int control; | ||
| 2385 | |||
| 2386 | /* until mdio is ready for next command */ | ||
| 2387 | MDIO_WAIT_FOR_USER_ACCESS; | ||
| 2388 | |||
| 2389 | control = (MDIO_USERACCESS_GO | | ||
| 2390 | MDIO_USERACCESS_WRITE | | ||
| 2391 | ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | | ||
| 2392 | ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | | ||
| 2393 | (phy_data & MDIO_USERACCESS_DATA)); | ||
| 2394 | emac_mdio_write(MDIO_USERACCESS(0), control); | ||
| 2395 | |||
| 2396 | return 0; | ||
| 2397 | } | ||
| 2398 | |||
| 2399 | static int emac_mii_reset(struct mii_bus *bus) | ||
| 2400 | { | ||
| 2401 | unsigned int clk_div; | ||
| 2402 | int mdio_bus_freq = emac_bus_frequency; | ||
| 2403 | |||
| 2404 | if (mdio_max_freq && mdio_bus_freq) | ||
| 2405 | clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); | ||
| 2406 | else | ||
| 2407 | clk_div = 0xFF; | ||
| 2408 | |||
| 2409 | clk_div &= MDIO_CONTROL_CLKDIV; | ||
| 2410 | |||
| 2411 | /* Set enable and clock divider in MDIOControl */ | ||
| 2412 | emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE)); | ||
| 2413 | |||
| 2414 | return 0; | ||
| 2415 | |||
| 2416 | } | ||
| 2417 | |||
| 2418 | static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL }; | ||
| 2419 | |||
| 2420 | /* emac_driver: EMAC MII bus structure */ | ||
| 2421 | |||
| 2422 | static struct mii_bus *emac_mii; | ||
| 2423 | |||
| 2424 | static void emac_adjust_link(struct net_device *ndev) | 1438 | static void emac_adjust_link(struct net_device *ndev) |
| 2425 | { | 1439 | { |
| 2426 | struct emac_priv *priv = netdev_priv(ndev); | 1440 | struct emac_priv *priv = netdev_priv(ndev); |
| @@ -2485,6 +1499,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) | |||
| 2485 | return -EOPNOTSUPP; | 1499 | return -EOPNOTSUPP; |
| 2486 | } | 1500 | } |
| 2487 | 1501 | ||
| 1502 | static int match_first_device(struct device *dev, void *data) | ||
| 1503 | { | ||
| 1504 | return 1; | ||
| 1505 | } | ||
| 1506 | |||
| 2488 | /** | 1507 | /** |
| 2489 | * emac_dev_open: EMAC device open | 1508 | * emac_dev_open: EMAC device open |
| 2490 | * @ndev: The DaVinci EMAC network adapter | 1509 | * @ndev: The DaVinci EMAC network adapter |
| @@ -2498,10 +1517,9 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) | |||
| 2498 | static int emac_dev_open(struct net_device *ndev) | 1517 | static int emac_dev_open(struct net_device *ndev) |
| 2499 | { | 1518 | { |
| 2500 | struct device *emac_dev = &ndev->dev; | 1519 | struct device *emac_dev = &ndev->dev; |
| 2501 | u32 rc, cnt, ch; | 1520 | u32 cnt; |
| 2502 | int phy_addr; | ||
| 2503 | struct resource *res; | 1521 | struct resource *res; |
| 2504 | int q, m; | 1522 | int q, m, ret; |
| 2505 | int i = 0; | 1523 | int i = 0; |
| 2506 | int k = 0; | 1524 | int k = 0; |
| 2507 | struct emac_priv *priv = netdev_priv(ndev); | 1525 | struct emac_priv *priv = netdev_priv(ndev); |
| @@ -2513,29 +1531,21 @@ static int emac_dev_open(struct net_device *ndev) | |||
| 2513 | /* Configuration items */ | 1531 | /* Configuration items */ |
| 2514 | priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; | 1532 | priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; |
| 2515 | 1533 | ||
| 2516 | /* Clear basic hardware */ | ||
| 2517 | for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) { | ||
| 2518 | emac_write(EMAC_TXHDP(ch), 0); | ||
| 2519 | emac_write(EMAC_RXHDP(ch), 0); | ||
| 2520 | emac_write(EMAC_RXHDP(ch), 0); | ||
| 2521 | emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); | ||
| 2522 | emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); | ||
| 2523 | } | ||
| 2524 | priv->mac_hash1 = 0; | 1534 | priv->mac_hash1 = 0; |
| 2525 | priv->mac_hash2 = 0; | 1535 | priv->mac_hash2 = 0; |
| 2526 | emac_write(EMAC_MACHASH1, 0); | 1536 | emac_write(EMAC_MACHASH1, 0); |
| 2527 | emac_write(EMAC_MACHASH2, 0); | 1537 | emac_write(EMAC_MACHASH2, 0); |
| 2528 | 1538 | ||
| 2529 | /* multi ch not supported - open 1 TX, 1RX ch by default */ | 1539 | for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) { |
| 2530 | rc = emac_init_txch(priv, EMAC_DEF_TX_CH); | 1540 | struct sk_buff *skb = emac_rx_alloc(priv); |
| 2531 | if (0 != rc) { | 1541 | |
| 2532 | dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed"); | 1542 | if (!skb) |
| 2533 | return rc; | 1543 | break; |
| 2534 | } | 1544 | |
| 2535 | rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr); | 1545 | ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, |
| 2536 | if (0 != rc) { | 1546 | skb_tailroom(skb), GFP_KERNEL); |
| 2537 | dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed"); | 1547 | if (WARN_ON(ret < 0)) |
| 2538 | return rc; | 1548 | break; |
| 2539 | } | 1549 | } |
| 2540 | 1550 | ||
| 2541 | /* Request IRQ */ | 1551 | /* Request IRQ */ |
| @@ -2560,28 +1570,28 @@ static int emac_dev_open(struct net_device *ndev) | |||
| 2560 | emac_set_coalesce(ndev, &coal); | 1570 | emac_set_coalesce(ndev, &coal); |
| 2561 | } | 1571 | } |
| 2562 | 1572 | ||
| 2563 | /* find the first phy */ | 1573 | cpdma_ctlr_start(priv->dma); |
| 1574 | |||
| 2564 | priv->phydev = NULL; | 1575 | priv->phydev = NULL; |
| 2565 | if (priv->phy_mask) { | 1576 | /* use the first phy on the bus if pdata did not give us a phy id */ |
| 2566 | emac_mii_reset(priv->mii_bus); | 1577 | if (!priv->phy_id) { |
| 2567 | for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { | 1578 | struct device *phy; |
| 2568 | if (priv->mii_bus->phy_map[phy_addr]) { | ||
| 2569 | priv->phydev = priv->mii_bus->phy_map[phy_addr]; | ||
| 2570 | break; | ||
| 2571 | } | ||
| 2572 | } | ||
| 2573 | 1579 | ||
| 2574 | if (!priv->phydev) { | 1580 | phy = bus_find_device(&mdio_bus_type, NULL, NULL, |
| 2575 | printk(KERN_ERR "%s: no PHY found\n", ndev->name); | 1581 | match_first_device); |
| 2576 | return -1; | 1582 | if (phy) |
| 2577 | } | 1583 | priv->phy_id = dev_name(phy); |
| 1584 | } | ||
| 2578 | 1585 | ||
| 2579 | priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev), | 1586 | if (priv->phy_id && *priv->phy_id) { |
| 2580 | &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); | 1587 | priv->phydev = phy_connect(ndev, priv->phy_id, |
| 1588 | &emac_adjust_link, 0, | ||
| 1589 | PHY_INTERFACE_MODE_MII); | ||
| 2581 | 1590 | ||
| 2582 | if (IS_ERR(priv->phydev)) { | 1591 | if (IS_ERR(priv->phydev)) { |
| 2583 | printk(KERN_ERR "%s: Could not attach to PHY\n", | 1592 | dev_err(emac_dev, "could not connect to phy %s\n", |
| 2584 | ndev->name); | 1593 | priv->phy_id); |
| 1594 | priv->phydev = NULL; | ||
| 2585 | return PTR_ERR(priv->phydev); | 1595 | return PTR_ERR(priv->phydev); |
| 2586 | } | 1596 | } |
| 2587 | 1597 | ||
| @@ -2589,12 +1599,13 @@ static int emac_dev_open(struct net_device *ndev) | |||
| 2589 | priv->speed = 0; | 1599 | priv->speed = 0; |
| 2590 | priv->duplex = ~0; | 1600 | priv->duplex = ~0; |
| 2591 | 1601 | ||
| 2592 | printk(KERN_INFO "%s: attached PHY driver [%s] " | 1602 | dev_info(emac_dev, "attached PHY driver [%s] " |
| 2593 | "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name, | 1603 | "(mii_bus:phy_addr=%s, id=%x)\n", |
| 2594 | priv->phydev->drv->name, dev_name(&priv->phydev->dev), | 1604 | priv->phydev->drv->name, dev_name(&priv->phydev->dev), |
| 2595 | priv->phydev->phy_id); | 1605 | priv->phydev->phy_id); |
| 2596 | } else{ | 1606 | } else { |
| 2597 | /* No PHY , fix the link, speed and duplex settings */ | 1607 | /* No PHY , fix the link, speed and duplex settings */ |
| 1608 | dev_notice(emac_dev, "no phy, defaulting to 100/full\n"); | ||
| 2598 | priv->link = 1; | 1609 | priv->link = 1; |
| 2599 | priv->speed = SPEED_100; | 1610 | priv->speed = SPEED_100; |
| 2600 | priv->duplex = DUPLEX_FULL; | 1611 | priv->duplex = DUPLEX_FULL; |
| @@ -2607,7 +1618,7 @@ static int emac_dev_open(struct net_device *ndev) | |||
| 2607 | if (netif_msg_drv(priv)) | 1618 | if (netif_msg_drv(priv)) |
| 2608 | dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); | 1619 | dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); |
| 2609 | 1620 | ||
| 2610 | if (priv->phy_mask) | 1621 | if (priv->phydev) |
| 2611 | phy_start(priv->phydev); | 1622 | phy_start(priv->phydev); |
| 2612 | 1623 | ||
| 2613 | return 0; | 1624 | return 0; |
| @@ -2648,10 +1659,7 @@ static int emac_dev_stop(struct net_device *ndev) | |||
| 2648 | 1659 | ||
| 2649 | netif_carrier_off(ndev); | 1660 | netif_carrier_off(ndev); |
| 2650 | emac_int_disable(priv); | 1661 | emac_int_disable(priv); |
| 2651 | emac_stop_txch(priv, EMAC_DEF_TX_CH); | 1662 | cpdma_ctlr_stop(priv->dma); |
| 2652 | emac_stop_rxch(priv, EMAC_DEF_RX_CH); | ||
| 2653 | emac_cleanup_txch(priv, EMAC_DEF_TX_CH); | ||
| 2654 | emac_cleanup_rxch(priv, EMAC_DEF_RX_CH); | ||
| 2655 | emac_write(EMAC_SOFTRESET, 1); | 1663 | emac_write(EMAC_SOFTRESET, 1); |
| 2656 | 1664 | ||
| 2657 | if (priv->phydev) | 1665 | if (priv->phydev) |
| @@ -2756,9 +1764,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
| 2756 | struct resource *res; | 1764 | struct resource *res; |
| 2757 | struct net_device *ndev; | 1765 | struct net_device *ndev; |
| 2758 | struct emac_priv *priv; | 1766 | struct emac_priv *priv; |
| 2759 | unsigned long size; | 1767 | unsigned long size, hw_ram_addr; |
| 2760 | struct emac_platform_data *pdata; | 1768 | struct emac_platform_data *pdata; |
| 2761 | struct device *emac_dev; | 1769 | struct device *emac_dev; |
| 1770 | struct cpdma_params dma_params; | ||
| 2762 | 1771 | ||
| 2763 | /* obtain emac clock from kernel */ | 1772 | /* obtain emac clock from kernel */ |
| 2764 | emac_clk = clk_get(&pdev->dev, NULL); | 1773 | emac_clk = clk_get(&pdev->dev, NULL); |
| @@ -2782,8 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
| 2782 | priv->ndev = ndev; | 1791 | priv->ndev = ndev; |
| 2783 | priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); | 1792 | priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); |
| 2784 | 1793 | ||
| 2785 | spin_lock_init(&priv->tx_lock); | ||
| 2786 | spin_lock_init(&priv->rx_lock); | ||
| 2787 | spin_lock_init(&priv->lock); | 1794 | spin_lock_init(&priv->lock); |
| 2788 | 1795 | ||
| 2789 | pdata = pdev->dev.platform_data; | 1796 | pdata = pdev->dev.platform_data; |
| @@ -2794,7 +1801,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
| 2794 | 1801 | ||
| 2795 | /* MAC addr and PHY mask , RMII enable info from platform_data */ | 1802 | /* MAC addr and PHY mask , RMII enable info from platform_data */ |
| 2796 | memcpy(priv->mac_addr, pdata->mac_addr, 6); | 1803 | memcpy(priv->mac_addr, pdata->mac_addr, 6); |
| 2797 | priv->phy_mask = pdata->phy_mask; | 1804 | priv->phy_id = pdata->phy_id; |
| 2798 | priv->rmii_en = pdata->rmii_en; | 1805 | priv->rmii_en = pdata->rmii_en; |
| 2799 | priv->version = pdata->version; | 1806 | priv->version = pdata->version; |
| 2800 | priv->int_enable = pdata->interrupt_enable; | 1807 | priv->int_enable = pdata->interrupt_enable; |
| @@ -2831,14 +1838,41 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
| 2831 | ndev->base_addr = (unsigned long)priv->remap_addr; | 1838 | ndev->base_addr = (unsigned long)priv->remap_addr; |
| 2832 | 1839 | ||
| 2833 | priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; | 1840 | priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; |
| 2834 | priv->ctrl_ram_size = pdata->ctrl_ram_size; | ||
| 2835 | priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; | ||
| 2836 | 1841 | ||
| 2837 | if (pdata->hw_ram_addr) | 1842 | hw_ram_addr = pdata->hw_ram_addr; |
| 2838 | priv->hw_ram_addr = pdata->hw_ram_addr; | 1843 | if (!hw_ram_addr) |
| 2839 | else | 1844 | hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; |
| 2840 | priv->hw_ram_addr = (u32 __force)res->start + | 1845 | |
| 2841 | pdata->ctrl_ram_offset; | 1846 | memset(&dma_params, 0, sizeof(dma_params)); |
| 1847 | dma_params.dev = emac_dev; | ||
| 1848 | dma_params.dmaregs = priv->emac_base; | ||
| 1849 | dma_params.rxthresh = priv->emac_base + 0x120; | ||
| 1850 | dma_params.rxfree = priv->emac_base + 0x140; | ||
| 1851 | dma_params.txhdp = priv->emac_base + 0x600; | ||
| 1852 | dma_params.rxhdp = priv->emac_base + 0x620; | ||
| 1853 | dma_params.txcp = priv->emac_base + 0x640; | ||
| 1854 | dma_params.rxcp = priv->emac_base + 0x660; | ||
| 1855 | dma_params.num_chan = EMAC_MAX_TXRX_CHANNELS; | ||
| 1856 | dma_params.min_packet_size = EMAC_DEF_MIN_ETHPKTSIZE; | ||
| 1857 | dma_params.desc_mem_phys = hw_ram_addr; | ||
| 1858 | dma_params.desc_mem_size = pdata->ctrl_ram_size; | ||
| 1859 | dma_params.desc_align = 16; | ||
| 1860 | |||
| 1861 | priv->dma = cpdma_ctlr_create(&dma_params); | ||
| 1862 | if (!priv->dma) { | ||
| 1863 | dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n"); | ||
| 1864 | rc = -ENOMEM; | ||
| 1865 | goto no_dma; | ||
| 1866 | } | ||
| 1867 | |||
| 1868 | priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), | ||
| 1869 | emac_tx_handler); | ||
| 1870 | priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), | ||
| 1871 | emac_rx_handler); | ||
| 1872 | if (WARN_ON(!priv->txchan || !priv->rxchan)) { | ||
| 1873 | rc = -ENOMEM; | ||
| 1874 | goto no_irq_res; | ||
| 1875 | } | ||
| 2842 | 1876 | ||
| 2843 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 1877 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| 2844 | if (!res) { | 1878 | if (!res) { |
| @@ -2871,32 +1905,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
| 2871 | } | 1905 | } |
| 2872 | 1906 | ||
| 2873 | 1907 | ||
| 2874 | /* MII/Phy intialisation, mdio bus registration */ | ||
| 2875 | emac_mii = mdiobus_alloc(); | ||
| 2876 | if (emac_mii == NULL) { | ||
| 2877 | dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n"); | ||
| 2878 | rc = -ENOMEM; | ||
| 2879 | goto mdio_alloc_err; | ||
| 2880 | } | ||
| 2881 | |||
| 2882 | priv->mii_bus = emac_mii; | ||
| 2883 | emac_mii->name = "emac-mii", | ||
| 2884 | emac_mii->read = emac_mii_read, | ||
| 2885 | emac_mii->write = emac_mii_write, | ||
| 2886 | emac_mii->reset = emac_mii_reset, | ||
| 2887 | emac_mii->irq = mii_irqs, | ||
| 2888 | emac_mii->phy_mask = ~(priv->phy_mask); | ||
| 2889 | emac_mii->parent = &pdev->dev; | ||
| 2890 | emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset; | ||
| 2891 | snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id); | ||
| 2892 | mdio_max_freq = pdata->mdio_max_freq; | ||
| 2893 | emac_mii->reset(emac_mii); | ||
| 2894 | |||
| 2895 | /* Register the MII bus */ | ||
| 2896 | rc = mdiobus_register(emac_mii); | ||
| 2897 | if (rc) | ||
| 2898 | goto mdiobus_quit; | ||
| 2899 | |||
| 2900 | if (netif_msg_probe(priv)) { | 1908 | if (netif_msg_probe(priv)) { |
| 2901 | dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ | 1909 | dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ |
| 2902 | "(regs: %p, irq: %d)\n", | 1910 | "(regs: %p, irq: %d)\n", |
| @@ -2904,13 +1912,15 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) | |||
| 2904 | } | 1912 | } |
| 2905 | return 0; | 1913 | return 0; |
| 2906 | 1914 | ||
| 2907 | mdiobus_quit: | ||
| 2908 | mdiobus_free(emac_mii); | ||
| 2909 | |||
| 2910 | netdev_reg_err: | 1915 | netdev_reg_err: |
| 2911 | mdio_alloc_err: | ||
| 2912 | clk_disable(emac_clk); | 1916 | clk_disable(emac_clk); |
| 2913 | no_irq_res: | 1917 | no_irq_res: |
| 1918 | if (priv->txchan) | ||
| 1919 | cpdma_chan_destroy(priv->txchan); | ||
| 1920 | if (priv->rxchan) | ||
| 1921 | cpdma_chan_destroy(priv->rxchan); | ||
| 1922 | cpdma_ctlr_destroy(priv->dma); | ||
| 1923 | no_dma: | ||
| 2914 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1924 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2915 | release_mem_region(res->start, res->end - res->start + 1); | 1925 | release_mem_region(res->start, res->end - res->start + 1); |
| 2916 | iounmap(priv->remap_addr); | 1926 | iounmap(priv->remap_addr); |
| @@ -2938,8 +1948,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) | |||
| 2938 | 1948 | ||
| 2939 | platform_set_drvdata(pdev, NULL); | 1949 | platform_set_drvdata(pdev, NULL); |
| 2940 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1950 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2941 | mdiobus_unregister(priv->mii_bus); | 1951 | |
| 2942 | mdiobus_free(priv->mii_bus); | 1952 | if (priv->txchan) |
| 1953 | cpdma_chan_destroy(priv->txchan); | ||
| 1954 | if (priv->rxchan) | ||
| 1955 | cpdma_chan_destroy(priv->rxchan); | ||
| 1956 | cpdma_ctlr_destroy(priv->dma); | ||
| 2943 | 1957 | ||
| 2944 | release_mem_region(res->start, res->end - res->start + 1); | 1958 | release_mem_region(res->start, res->end - res->start + 1); |
| 2945 | 1959 | ||
diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c new file mode 100644 index 000000000000..7615040df756 --- /dev/null +++ b/drivers/net/davinci_mdio.c | |||
| @@ -0,0 +1,475 @@ | |||
| 1 | /* | ||
| 2 | * DaVinci MDIO Module driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Texas Instruments. | ||
| 5 | * | ||
| 6 | * Shamelessly ripped out of davinci_emac.c, original copyrights follow: | ||
| 7 | * | ||
| 8 | * Copyright (C) 2009 Texas Instruments. | ||
| 9 | * | ||
| 10 | * --------------------------------------------------------------------------- | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2 of the License, or | ||
| 15 | * (at your option) any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 25 | * --------------------------------------------------------------------------- | ||
| 26 | */ | ||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/kernel.h> | ||
| 29 | #include <linux/platform_device.h> | ||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/sched.h> | ||
| 32 | #include <linux/slab.h> | ||
| 33 | #include <linux/phy.h> | ||
| 34 | #include <linux/clk.h> | ||
| 35 | #include <linux/err.h> | ||
| 36 | #include <linux/io.h> | ||
| 37 | #include <linux/davinci_emac.h> | ||
| 38 | |||
| 39 | /* | ||
| 40 | * This timeout definition is a worst-case ultra defensive measure against | ||
| 41 | * unexpected controller lock ups. Ideally, we should never ever hit this | ||
| 42 | * scenario in practice. | ||
| 43 | */ | ||
| 44 | #define MDIO_TIMEOUT 100 /* msecs */ | ||
| 45 | |||
| 46 | #define PHY_REG_MASK 0x1f | ||
| 47 | #define PHY_ID_MASK 0x1f | ||
| 48 | |||
| 49 | #define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ | ||
| 50 | |||
| 51 | struct davinci_mdio_regs { | ||
| 52 | u32 version; | ||
| 53 | u32 control; | ||
| 54 | #define CONTROL_IDLE BIT(31) | ||
| 55 | #define CONTROL_ENABLE BIT(30) | ||
| 56 | #define CONTROL_MAX_DIV (0xff) | ||
| 57 | |||
| 58 | u32 alive; | ||
| 59 | u32 link; | ||
| 60 | u32 linkintraw; | ||
| 61 | u32 linkintmasked; | ||
| 62 | u32 __reserved_0[2]; | ||
| 63 | u32 userintraw; | ||
| 64 | u32 userintmasked; | ||
| 65 | u32 userintmaskset; | ||
| 66 | u32 userintmaskclr; | ||
| 67 | u32 __reserved_1[20]; | ||
| 68 | |||
| 69 | struct { | ||
| 70 | u32 access; | ||
| 71 | #define USERACCESS_GO BIT(31) | ||
| 72 | #define USERACCESS_WRITE BIT(30) | ||
| 73 | #define USERACCESS_ACK BIT(29) | ||
| 74 | #define USERACCESS_READ (0) | ||
| 75 | #define USERACCESS_DATA (0xffff) | ||
| 76 | |||
| 77 | u32 physel; | ||
| 78 | } user[0]; | ||
| 79 | }; | ||
| 80 | |||
| 81 | struct mdio_platform_data default_pdata = { | ||
| 82 | .bus_freq = DEF_OUT_FREQ, | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct davinci_mdio_data { | ||
| 86 | struct mdio_platform_data pdata; | ||
| 87 | struct davinci_mdio_regs __iomem *regs; | ||
| 88 | spinlock_t lock; | ||
| 89 | struct clk *clk; | ||
| 90 | struct device *dev; | ||
| 91 | struct mii_bus *bus; | ||
| 92 | bool suspended; | ||
| 93 | unsigned long access_time; /* jiffies */ | ||
| 94 | }; | ||
| 95 | |||
| 96 | static void __davinci_mdio_reset(struct davinci_mdio_data *data) | ||
| 97 | { | ||
| 98 | u32 mdio_in, div, mdio_out_khz, access_time; | ||
| 99 | |||
| 100 | mdio_in = clk_get_rate(data->clk); | ||
| 101 | div = (mdio_in / data->pdata.bus_freq) - 1; | ||
| 102 | if (div > CONTROL_MAX_DIV) | ||
| 103 | div = CONTROL_MAX_DIV; | ||
| 104 | |||
| 105 | /* set enable and clock divider */ | ||
| 106 | __raw_writel(div | CONTROL_ENABLE, &data->regs->control); | ||
| 107 | |||
| 108 | /* | ||
| 109 | * One mdio transaction consists of: | ||
| 110 | * 32 bits of preamble | ||
| 111 | * 32 bits of transferred data | ||
| 112 | * 24 bits of bus yield (not needed unless shared?) | ||
| 113 | */ | ||
| 114 | mdio_out_khz = mdio_in / (1000 * (div + 1)); | ||
| 115 | access_time = (88 * 1000) / mdio_out_khz; | ||
| 116 | |||
| 117 | /* | ||
| 118 | * In the worst case, we could be kicking off a user-access immediately | ||
| 119 | * after the mdio bus scan state-machine triggered its own read. If | ||
| 120 | * so, our request could get deferred by one access cycle. We | ||
| 121 | * defensively allow for 4 access cycles. | ||
| 122 | */ | ||
| 123 | data->access_time = usecs_to_jiffies(access_time * 4); | ||
| 124 | if (!data->access_time) | ||
| 125 | data->access_time = 1; | ||
| 126 | } | ||
| 127 | |||
| 128 | static int davinci_mdio_reset(struct mii_bus *bus) | ||
| 129 | { | ||
| 130 | struct davinci_mdio_data *data = bus->priv; | ||
| 131 | u32 phy_mask, ver; | ||
| 132 | |||
| 133 | __davinci_mdio_reset(data); | ||
| 134 | |||
| 135 | /* wait for scan logic to settle */ | ||
| 136 | msleep(PHY_MAX_ADDR * data->access_time); | ||
| 137 | |||
| 138 | /* dump hardware version info */ | ||
| 139 | ver = __raw_readl(&data->regs->version); | ||
| 140 | dev_info(data->dev, "davinci mdio revision %d.%d\n", | ||
| 141 | (ver >> 8) & 0xff, ver & 0xff); | ||
| 142 | |||
| 143 | /* get phy mask from the alive register */ | ||
| 144 | phy_mask = __raw_readl(&data->regs->alive); | ||
| 145 | if (phy_mask) { | ||
| 146 | /* restrict mdio bus to live phys only */ | ||
| 147 | dev_info(data->dev, "detected phy mask %x\n", ~phy_mask); | ||
| 148 | phy_mask = ~phy_mask; | ||
| 149 | } else { | ||
| 150 | /* desperately scan all phys */ | ||
| 151 | dev_warn(data->dev, "no live phy, scanning all\n"); | ||
| 152 | phy_mask = 0; | ||
| 153 | } | ||
| 154 | data->bus->phy_mask = phy_mask; | ||
| 155 | |||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* wait until hardware is ready for another user access */ | ||
| 160 | static inline int wait_for_user_access(struct davinci_mdio_data *data) | ||
| 161 | { | ||
| 162 | struct davinci_mdio_regs __iomem *regs = data->regs; | ||
| 163 | unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); | ||
| 164 | u32 reg; | ||
| 165 | |||
| 166 | while (time_after(timeout, jiffies)) { | ||
| 167 | reg = __raw_readl(®s->user[0].access); | ||
| 168 | if ((reg & USERACCESS_GO) == 0) | ||
| 169 | return 0; | ||
| 170 | |||
| 171 | reg = __raw_readl(®s->control); | ||
| 172 | if ((reg & CONTROL_IDLE) == 0) | ||
| 173 | continue; | ||
| 174 | |||
| 175 | /* | ||
| 176 | * An emac soft_reset may have clobbered the mdio controller's | ||
| 177 | * state machine. We need to reset and retry the current | ||
| 178 | * operation | ||
| 179 | */ | ||
| 180 | dev_warn(data->dev, "resetting idled controller\n"); | ||
| 181 | __davinci_mdio_reset(data); | ||
| 182 | return -EAGAIN; | ||
| 183 | } | ||
| 184 | dev_err(data->dev, "timed out waiting for user access\n"); | ||
| 185 | return -ETIMEDOUT; | ||
| 186 | } | ||
| 187 | |||
| 188 | /* wait until hardware state machine is idle */ | ||
| 189 | static inline int wait_for_idle(struct davinci_mdio_data *data) | ||
| 190 | { | ||
| 191 | struct davinci_mdio_regs __iomem *regs = data->regs; | ||
| 192 | unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); | ||
| 193 | |||
| 194 | while (time_after(timeout, jiffies)) { | ||
| 195 | if (__raw_readl(®s->control) & CONTROL_IDLE) | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | dev_err(data->dev, "timed out waiting for idle\n"); | ||
| 199 | return -ETIMEDOUT; | ||
| 200 | } | ||
| 201 | |||
| 202 | static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) | ||
| 203 | { | ||
| 204 | struct davinci_mdio_data *data = bus->priv; | ||
| 205 | u32 reg; | ||
| 206 | int ret; | ||
| 207 | |||
| 208 | if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) | ||
| 209 | return -EINVAL; | ||
| 210 | |||
| 211 | spin_lock(&data->lock); | ||
| 212 | |||
| 213 | if (data->suspended) { | ||
| 214 | spin_unlock(&data->lock); | ||
| 215 | return -ENODEV; | ||
| 216 | } | ||
| 217 | |||
| 218 | reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | | ||
| 219 | (phy_id << 16)); | ||
| 220 | |||
| 221 | while (1) { | ||
| 222 | ret = wait_for_user_access(data); | ||
| 223 | if (ret == -EAGAIN) | ||
| 224 | continue; | ||
| 225 | if (ret < 0) | ||
| 226 | break; | ||
| 227 | |||
| 228 | __raw_writel(reg, &data->regs->user[0].access); | ||
| 229 | |||
| 230 | ret = wait_for_user_access(data); | ||
| 231 | if (ret == -EAGAIN) | ||
| 232 | continue; | ||
| 233 | if (ret < 0) | ||
| 234 | break; | ||
| 235 | |||
| 236 | reg = __raw_readl(&data->regs->user[0].access); | ||
| 237 | ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | |||
| 241 | spin_unlock(&data->lock); | ||
| 242 | |||
| 243 | return ret; | ||
| 244 | } | ||
| 245 | |||
| 246 | static int davinci_mdio_write(struct mii_bus *bus, int phy_id, | ||
| 247 | int phy_reg, u16 phy_data) | ||
| 248 | { | ||
| 249 | struct davinci_mdio_data *data = bus->priv; | ||
| 250 | u32 reg; | ||
| 251 | int ret; | ||
| 252 | |||
| 253 | if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) | ||
| 254 | return -EINVAL; | ||
| 255 | |||
| 256 | spin_lock(&data->lock); | ||
| 257 | |||
| 258 | if (data->suspended) { | ||
| 259 | spin_unlock(&data->lock); | ||
| 260 | return -ENODEV; | ||
| 261 | } | ||
| 262 | |||
| 263 | reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) | | ||
| 264 | (phy_id << 16) | (phy_data & USERACCESS_DATA)); | ||
| 265 | |||
| 266 | while (1) { | ||
| 267 | ret = wait_for_user_access(data); | ||
| 268 | if (ret == -EAGAIN) | ||
| 269 | continue; | ||
| 270 | if (ret < 0) | ||
| 271 | break; | ||
| 272 | |||
| 273 | __raw_writel(reg, &data->regs->user[0].access); | ||
| 274 | |||
| 275 | ret = wait_for_user_access(data); | ||
| 276 | if (ret == -EAGAIN) | ||
| 277 | continue; | ||
| 278 | break; | ||
| 279 | } | ||
| 280 | |||
| 281 | spin_unlock(&data->lock); | ||
| 282 | |||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | static int __devinit davinci_mdio_probe(struct platform_device *pdev) | ||
| 287 | { | ||
| 288 | struct mdio_platform_data *pdata = pdev->dev.platform_data; | ||
| 289 | struct device *dev = &pdev->dev; | ||
| 290 | struct davinci_mdio_data *data; | ||
| 291 | struct resource *res; | ||
| 292 | struct phy_device *phy; | ||
| 293 | int ret, addr; | ||
| 294 | |||
| 295 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 296 | if (!data) { | ||
| 297 | dev_err(dev, "failed to alloc device data\n"); | ||
| 298 | return -ENOMEM; | ||
| 299 | } | ||
| 300 | |||
| 301 | data->pdata = pdata ? (*pdata) : default_pdata; | ||
| 302 | |||
| 303 | data->bus = mdiobus_alloc(); | ||
| 304 | if (!data->bus) { | ||
| 305 | dev_err(dev, "failed to alloc mii bus\n"); | ||
| 306 | ret = -ENOMEM; | ||
| 307 | goto bail_out; | ||
| 308 | } | ||
| 309 | |||
| 310 | data->bus->name = dev_name(dev); | ||
| 311 | data->bus->read = davinci_mdio_read, | ||
| 312 | data->bus->write = davinci_mdio_write, | ||
| 313 | data->bus->reset = davinci_mdio_reset, | ||
| 314 | data->bus->parent = dev; | ||
| 315 | data->bus->priv = data; | ||
| 316 | snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); | ||
| 317 | |||
| 318 | data->clk = clk_get(dev, NULL); | ||
| 319 | if (IS_ERR(data->clk)) { | ||
| 320 | data->clk = NULL; | ||
| 321 | dev_err(dev, "failed to get device clock\n"); | ||
| 322 | ret = PTR_ERR(data->clk); | ||
| 323 | goto bail_out; | ||
| 324 | } | ||
| 325 | |||
| 326 | clk_enable(data->clk); | ||
| 327 | |||
| 328 | dev_set_drvdata(dev, data); | ||
| 329 | data->dev = dev; | ||
| 330 | spin_lock_init(&data->lock); | ||
| 331 | |||
| 332 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 333 | if (!res) { | ||
| 334 | dev_err(dev, "could not find register map resource\n"); | ||
| 335 | ret = -ENOENT; | ||
| 336 | goto bail_out; | ||
| 337 | } | ||
| 338 | |||
| 339 | res = devm_request_mem_region(dev, res->start, resource_size(res), | ||
| 340 | dev_name(dev)); | ||
| 341 | if (!res) { | ||
| 342 | dev_err(dev, "could not allocate register map resource\n"); | ||
| 343 | ret = -ENXIO; | ||
| 344 | goto bail_out; | ||
| 345 | } | ||
| 346 | |||
| 347 | data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); | ||
| 348 | if (!data->regs) { | ||
| 349 | dev_err(dev, "could not map mdio registers\n"); | ||
| 350 | ret = -ENOMEM; | ||
| 351 | goto bail_out; | ||
| 352 | } | ||
| 353 | |||
| 354 | /* register the mii bus */ | ||
| 355 | ret = mdiobus_register(data->bus); | ||
| 356 | if (ret) | ||
| 357 | goto bail_out; | ||
| 358 | |||
| 359 | /* scan and dump the bus */ | ||
| 360 | for (addr = 0; addr < PHY_MAX_ADDR; addr++) { | ||
| 361 | phy = data->bus->phy_map[addr]; | ||
| 362 | if (phy) { | ||
| 363 | dev_info(dev, "phy[%d]: device %s, driver %s\n", | ||
| 364 | phy->addr, dev_name(&phy->dev), | ||
| 365 | phy->drv ? phy->drv->name : "unknown"); | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | return 0; | ||
| 370 | |||
| 371 | bail_out: | ||
| 372 | if (data->bus) | ||
| 373 | mdiobus_free(data->bus); | ||
| 374 | |||
| 375 | if (data->clk) { | ||
| 376 | clk_disable(data->clk); | ||
| 377 | clk_put(data->clk); | ||
| 378 | } | ||
| 379 | |||
| 380 | kfree(data); | ||
| 381 | |||
| 382 | return ret; | ||
| 383 | } | ||
| 384 | |||
| 385 | static int __devexit davinci_mdio_remove(struct platform_device *pdev) | ||
| 386 | { | ||
| 387 | struct device *dev = &pdev->dev; | ||
| 388 | struct davinci_mdio_data *data = dev_get_drvdata(dev); | ||
| 389 | |||
| 390 | if (data->bus) | ||
| 391 | mdiobus_free(data->bus); | ||
| 392 | |||
| 393 | if (data->clk) { | ||
| 394 | clk_disable(data->clk); | ||
| 395 | clk_put(data->clk); | ||
| 396 | } | ||
| 397 | |||
| 398 | dev_set_drvdata(dev, NULL); | ||
| 399 | |||
| 400 | kfree(data); | ||
| 401 | |||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int davinci_mdio_suspend(struct device *dev) | ||
| 406 | { | ||
| 407 | struct davinci_mdio_data *data = dev_get_drvdata(dev); | ||
| 408 | u32 ctrl; | ||
| 409 | |||
| 410 | spin_lock(&data->lock); | ||
| 411 | |||
| 412 | /* shutdown the scan state machine */ | ||
| 413 | ctrl = __raw_readl(&data->regs->control); | ||
| 414 | ctrl &= ~CONTROL_ENABLE; | ||
| 415 | __raw_writel(ctrl, &data->regs->control); | ||
| 416 | wait_for_idle(data); | ||
| 417 | |||
| 418 | if (data->clk) | ||
| 419 | clk_disable(data->clk); | ||
| 420 | |||
| 421 | data->suspended = true; | ||
| 422 | spin_unlock(&data->lock); | ||
| 423 | |||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | |||
| 427 | static int davinci_mdio_resume(struct device *dev) | ||
| 428 | { | ||
| 429 | struct davinci_mdio_data *data = dev_get_drvdata(dev); | ||
| 430 | u32 ctrl; | ||
| 431 | |||
| 432 | spin_lock(&data->lock); | ||
| 433 | if (data->clk) | ||
| 434 | clk_enable(data->clk); | ||
| 435 | |||
| 436 | /* restart the scan state machine */ | ||
| 437 | ctrl = __raw_readl(&data->regs->control); | ||
| 438 | ctrl |= CONTROL_ENABLE; | ||
| 439 | __raw_writel(ctrl, &data->regs->control); | ||
| 440 | |||
| 441 | data->suspended = false; | ||
| 442 | spin_unlock(&data->lock); | ||
| 443 | |||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | static const struct dev_pm_ops davinci_mdio_pm_ops = { | ||
| 448 | .suspend = davinci_mdio_suspend, | ||
| 449 | .resume = davinci_mdio_resume, | ||
| 450 | }; | ||
| 451 | |||
| 452 | static struct platform_driver davinci_mdio_driver = { | ||
| 453 | .driver = { | ||
| 454 | .name = "davinci_mdio", | ||
| 455 | .owner = THIS_MODULE, | ||
| 456 | .pm = &davinci_mdio_pm_ops, | ||
| 457 | }, | ||
| 458 | .probe = davinci_mdio_probe, | ||
| 459 | .remove = __devexit_p(davinci_mdio_remove), | ||
| 460 | }; | ||
| 461 | |||
| 462 | static int __init davinci_mdio_init(void) | ||
| 463 | { | ||
| 464 | return platform_driver_register(&davinci_mdio_driver); | ||
| 465 | } | ||
| 466 | device_initcall(davinci_mdio_init); | ||
| 467 | |||
| 468 | static void __exit davinci_mdio_exit(void) | ||
| 469 | { | ||
| 470 | platform_driver_unregister(&davinci_mdio_driver); | ||
| 471 | } | ||
| 472 | module_exit(davinci_mdio_exit); | ||
| 473 | |||
| 474 | MODULE_LICENSE("GPL"); | ||
| 475 | MODULE_DESCRIPTION("DaVinci MDIO driver"); | ||
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 7c930dba477c..5dd428532f79 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h | |||
| @@ -14,16 +14,26 @@ | |||
| 14 | #include <linux/if_ether.h> | 14 | #include <linux/if_ether.h> |
| 15 | #include <linux/memory.h> | 15 | #include <linux/memory.h> |
| 16 | 16 | ||
| 17 | struct mdio_platform_data { | ||
| 18 | unsigned long bus_freq; | ||
| 19 | }; | ||
| 20 | |||
| 17 | struct emac_platform_data { | 21 | struct emac_platform_data { |
| 18 | char mac_addr[ETH_ALEN]; | 22 | char mac_addr[ETH_ALEN]; |
| 19 | u32 ctrl_reg_offset; | 23 | u32 ctrl_reg_offset; |
| 20 | u32 ctrl_mod_reg_offset; | 24 | u32 ctrl_mod_reg_offset; |
| 21 | u32 ctrl_ram_offset; | 25 | u32 ctrl_ram_offset; |
| 22 | u32 hw_ram_addr; | 26 | u32 hw_ram_addr; |
| 23 | u32 mdio_reg_offset; | ||
| 24 | u32 ctrl_ram_size; | 27 | u32 ctrl_ram_size; |
| 25 | u32 phy_mask; | 28 | |
| 26 | u32 mdio_max_freq; | 29 | /* |
| 30 | * phy_id can be one of the following: | ||
| 31 | * - NULL : use the first phy on the bus, | ||
| 32 | * - "" : force to 100/full, no mdio control | ||
| 33 | * - "<bus>:<addr>" : use the specified bus and phy | ||
| 34 | */ | ||
| 35 | const char *phy_id; | ||
| 36 | |||
| 27 | u8 rmii_en; | 37 | u8 rmii_en; |
| 28 | u8 version; | 38 | u8 version; |
| 29 | void (*interrupt_enable) (void); | 39 | void (*interrupt_enable) (void); |
