diff options
286 files changed, 6895 insertions, 2801 deletions
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 986946613542..ec0a38ef3145 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy | |||
@@ -23,7 +23,7 @@ Description: | |||
23 | lsm: [[subj_user=] [subj_role=] [subj_type=] | 23 | lsm: [[subj_user=] [subj_role=] [subj_type=] |
24 | [obj_user=] [obj_role=] [obj_type=]] | 24 | [obj_user=] [obj_role=] [obj_type=]] |
25 | 25 | ||
26 | base: func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK] | 26 | base: func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK][MODULE_CHECK] |
27 | mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] | 27 | mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] |
28 | fsmagic:= hex value | 28 | fsmagic:= hex value |
29 | uid:= decimal value | 29 | uid:= decimal value |
@@ -53,6 +53,7 @@ Description: | |||
53 | measure func=BPRM_CHECK | 53 | measure func=BPRM_CHECK |
54 | measure func=FILE_MMAP mask=MAY_EXEC | 54 | measure func=FILE_MMAP mask=MAY_EXEC |
55 | measure func=FILE_CHECK mask=MAY_READ uid=0 | 55 | measure func=FILE_CHECK mask=MAY_READ uid=0 |
56 | measure func=MODULE_CHECK uid=0 | ||
56 | appraise fowner=0 | 57 | appraise fowner=0 |
57 | 58 | ||
58 | The default policy measures all executables in bprm_check, | 59 | The default policy measures all executables in bprm_check, |
diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt index 49fc7ada929a..3545ea704b50 100644 --- a/Documentation/devicetree/bindings/arm/davinci/nand.txt +++ b/Documentation/devicetree/bindings/arm/davinci/nand.txt | |||
@@ -23,6 +23,9 @@ Recommended properties : | |||
23 | - ti,davinci-nand-buswidth: buswidth 8 or 16 | 23 | - ti,davinci-nand-buswidth: buswidth 8 or 16 |
24 | - ti,davinci-nand-use-bbt: use flash based bad block table support. | 24 | - ti,davinci-nand-use-bbt: use flash based bad block table support. |
25 | 25 | ||
26 | nand device bindings may contain additional sub-nodes describing | ||
27 | partitions of the address space. See partition.txt for more detail. | ||
28 | |||
26 | Example(da850 EVM ): | 29 | Example(da850 EVM ): |
27 | nand_cs3@62000000 { | 30 | nand_cs3@62000000 { |
28 | compatible = "ti,davinci-nand"; | 31 | compatible = "ti,davinci-nand"; |
@@ -35,4 +38,9 @@ nand_cs3@62000000 { | |||
35 | ti,davinci-ecc-mode = "hw"; | 38 | ti,davinci-ecc-mode = "hw"; |
36 | ti,davinci-ecc-bits = <4>; | 39 | ti,davinci-ecc-bits = <4>; |
37 | ti,davinci-nand-use-bbt; | 40 | ti,davinci-nand-use-bbt; |
41 | |||
42 | partition@180000 { | ||
43 | label = "ubifs"; | ||
44 | reg = <0x180000 0x7e80000>; | ||
45 | }; | ||
38 | }; | 46 | }; |
diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt new file mode 100644 index 000000000000..b04d03a1d499 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | * Denali NAND controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : should be "denali,denali-nand-dt" | ||
5 | - reg : should contain registers location and length for data and reg. | ||
6 | - reg-names: Should contain the reg names "nand_data" and "denali_reg" | ||
7 | - interrupts : The interrupt number. | ||
8 | - dm-mask : DMA bit mask | ||
9 | |||
10 | The device tree may optionally contain sub-nodes describing partitions of the | ||
11 | address space. See partition.txt for more detail. | ||
12 | |||
13 | Examples: | ||
14 | |||
15 | nand: nand@ff900000 { | ||
16 | #address-cells = <1>; | ||
17 | #size-cells = <1>; | ||
18 | compatible = "denali,denali-nand-dt"; | ||
19 | reg = <0xff900000 0x100000>, <0xffb80000 0x10000>; | ||
20 | reg-names = "nand_data", "denali_reg"; | ||
21 | interrupts = <0 144 4>; | ||
22 | dma-mask = <0xffffffff>; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/flctl-nand.txt b/Documentation/devicetree/bindings/mtd/flctl-nand.txt new file mode 100644 index 000000000000..427f46dc60ad --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/flctl-nand.txt | |||
@@ -0,0 +1,49 @@ | |||
1 | FLCTL NAND controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "renesas,shmobile-flctl-sh7372" | ||
5 | - reg : Address range of the FLCTL | ||
6 | - interrupts : flste IRQ number | ||
7 | - nand-bus-width : bus width to NAND chip | ||
8 | |||
9 | Optional properties: | ||
10 | - dmas: DMA specifier(s) | ||
11 | - dma-names: name for each DMA specifier. Valid names are | ||
12 | "data_tx", "data_rx", "ecc_tx", "ecc_rx" | ||
13 | |||
14 | The DMA fields are not used yet in the driver but are listed here for | ||
15 | completing the bindings. | ||
16 | |||
17 | The device tree may optionally contain sub-nodes describing partitions of the | ||
18 | address space. See partition.txt for more detail. | ||
19 | |||
20 | Example: | ||
21 | |||
22 | flctl@e6a30000 { | ||
23 | #address-cells = <1>; | ||
24 | #size-cells = <1>; | ||
25 | compatible = "renesas,shmobile-flctl-sh7372"; | ||
26 | reg = <0xe6a30000 0x100>; | ||
27 | interrupts = <0x0d80>; | ||
28 | |||
29 | nand-bus-width = <16>; | ||
30 | |||
31 | dmas = <&dmac 1 /* data_tx */ | ||
32 | &dmac 2;> /* data_rx */ | ||
33 | dma-names = "data_tx", "data_rx"; | ||
34 | |||
35 | system@0 { | ||
36 | label = "system"; | ||
37 | reg = <0x0 0x8000000>; | ||
38 | }; | ||
39 | |||
40 | userdata@8000000 { | ||
41 | label = "userdata"; | ||
42 | reg = <0x8000000 0x10000000>; | ||
43 | }; | ||
44 | |||
45 | cache@18000000 { | ||
46 | label = "cache"; | ||
47 | reg = <0x18000000 0x8000000>; | ||
48 | }; | ||
49 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt index e2c663b354d2..e3ea32e7de3e 100644 --- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt | |||
@@ -3,9 +3,7 @@ | |||
3 | Required properties: | 3 | Required properties: |
4 | - compatible : "st,spear600-fsmc-nand" | 4 | - compatible : "st,spear600-fsmc-nand" |
5 | - reg : Address range of the mtd chip | 5 | - reg : Address range of the mtd chip |
6 | - reg-names: Should contain the reg names "fsmc_regs" and "nand_data" | 6 | - reg-names: Should contain the reg names "fsmc_regs", "nand_data", "nand_addr" and "nand_cmd" |
7 | - st,ale-off : Chip specific offset to ALE | ||
8 | - st,cle-off : Chip specific offset to CLE | ||
9 | 7 | ||
10 | Optional properties: | 8 | Optional properties: |
11 | - bank-width : Width (in bytes) of the device. If not present, the width | 9 | - bank-width : Width (in bytes) of the device. If not present, the width |
@@ -19,10 +17,10 @@ Example: | |||
19 | #address-cells = <1>; | 17 | #address-cells = <1>; |
20 | #size-cells = <1>; | 18 | #size-cells = <1>; |
21 | reg = <0xd1800000 0x1000 /* FSMC Register */ | 19 | reg = <0xd1800000 0x1000 /* FSMC Register */ |
22 | 0xd2000000 0x4000>; /* NAND Base */ | 20 | 0xd2000000 0x0010 /* NAND Base DATA */ |
23 | reg-names = "fsmc_regs", "nand_data"; | 21 | 0xd2020000 0x0010 /* NAND Base ADDR */ |
24 | st,ale-off = <0x20000>; | 22 | 0xd2010000 0x0010>; /* NAND Base CMD */ |
25 | st,cle-off = <0x10000>; | 23 | reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd"; |
26 | 24 | ||
27 | bank-width = <1>; | 25 | bank-width = <1>; |
28 | nand-skip-bbtscan; | 26 | nand-skip-bbtscan; |
diff --git a/Documentation/devicetree/bindings/mtd/m25p80.txt b/Documentation/devicetree/bindings/mtd/m25p80.txt new file mode 100644 index 000000000000..6d3d57609470 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/m25p80.txt | |||
@@ -0,0 +1,29 @@ | |||
1 | * MTD SPI driver for ST M25Pxx (and similar) serial flash chips | ||
2 | |||
3 | Required properties: | ||
4 | - #address-cells, #size-cells : Must be present if the device has sub-nodes | ||
5 | representing partitions. | ||
6 | - compatible : Should be the manufacturer and the name of the chip. Bear in mind | ||
7 | the DT binding is not Linux-only, but in case of Linux, see the | ||
8 | "m25p_ids" table in drivers/mtd/devices/m25p80.c for the list of | ||
9 | supported chips. | ||
10 | - reg : Chip-Select number | ||
11 | - spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at | ||
12 | |||
13 | Optional properties: | ||
14 | - m25p,fast-read : Use the "fast read" opcode to read data from the chip instead | ||
15 | of the usual "read" opcode. This opcode is not supported by | ||
16 | all chips and support for it can not be detected at runtime. | ||
17 | Refer to your chips' datasheet to check if this is supported | ||
18 | by your chip. | ||
19 | |||
20 | Example: | ||
21 | |||
22 | flash: m25p80@0 { | ||
23 | #address-cells = <1>; | ||
24 | #size-cells = <1>; | ||
25 | compatible = "spansion,m25p80"; | ||
26 | reg = <0>; | ||
27 | spi-max-frequency = <40000000>; | ||
28 | m25p,fast-read; | ||
29 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt index 94de19b8f16b..dab7847fc800 100644 --- a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt +++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt | |||
@@ -23,6 +23,9 @@ file systems on embedded devices. | |||
23 | unaligned accesses as implemented in the JFFS2 code via memcpy(). | 23 | unaligned accesses as implemented in the JFFS2 code via memcpy(). |
24 | By defining "no-unaligned-direct-access", the flash will not be | 24 | By defining "no-unaligned-direct-access", the flash will not be |
25 | exposed directly to the MTD users (e.g. JFFS2) any more. | 25 | exposed directly to the MTD users (e.g. JFFS2) any more. |
26 | - linux,mtd-name: allow to specify the mtd name for retro capability with | ||
27 | physmap-flash drivers as boot loader pass the mtd partition via the old | ||
28 | device name physmap-flash. | ||
26 | 29 | ||
27 | For JEDEC compatible devices, the following additional properties | 30 | For JEDEC compatible devices, the following additional properties |
28 | are defined: | 31 | are defined: |
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt new file mode 100644 index 000000000000..131e8c11d26f --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | TI SOC ECAP based APWM controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Must be "ti,am33xx-ecap" | ||
5 | - #pwm-cells: Should be 3. Number of cells being used to specify PWM property. | ||
6 | First cell specifies the per-chip index of the PWM to use, the second | ||
7 | cell is the period in nanoseconds and bit 0 in the third cell is used to | ||
8 | encode the polarity of PWM output. Set bit 0 of the third in PWM specifier | ||
9 | to 1 for inverse polarity & set to 0 for normal polarity. | ||
10 | - reg: physical base address and size of the registers map. | ||
11 | |||
12 | Optional properties: | ||
13 | - ti,hwmods: Name of the hwmod associated to the ECAP: | ||
14 | "ecap<x>", <x> being the 0-based instance number from the HW spec | ||
15 | |||
16 | Example: | ||
17 | |||
18 | ecap0: ecap@0 { | ||
19 | compatible = "ti,am33xx-ecap"; | ||
20 | #pwm-cells = <3>; | ||
21 | reg = <0x48300100 0x80>; | ||
22 | ti,hwmods = "ecap0"; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt new file mode 100644 index 000000000000..4fc7079d822e --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | TI SOC EHRPWM based PWM controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : Must be "ti,am33xx-ehrpwm" | ||
5 | - #pwm-cells: Should be 3. Number of cells being used to specify PWM property. | ||
6 | First cell specifies the per-chip index of the PWM to use, the second | ||
7 | cell is the period in nanoseconds and bit 0 in the third cell is used to | ||
8 | encode the polarity of PWM output. Set bit 0 of the third in PWM specifier | ||
9 | to 1 for inverse polarity & set to 0 for normal polarity. | ||
10 | - reg: physical base address and size of the registers map. | ||
11 | |||
12 | Optional properties: | ||
13 | - ti,hwmods: Name of the hwmod associated to the EHRPWM: | ||
14 | "ehrpwm<x>", <x> being the 0-based instance number from the HW spec | ||
15 | |||
16 | Example: | ||
17 | |||
18 | ehrpwm0: ehrpwm@0 { | ||
19 | compatible = "ti,am33xx-ehrpwm"; | ||
20 | #pwm-cells = <3>; | ||
21 | reg = <0x48300200 0x100>; | ||
22 | ti,hwmods = "ehrpwm0"; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt new file mode 100644 index 000000000000..f7eae77f8354 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt | |||
@@ -0,0 +1,31 @@ | |||
1 | TI SOC based PWM Subsystem | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Must be "ti,am33xx-pwmss"; | ||
5 | - reg: physical base address and size of the registers map. | ||
6 | - address-cells: Specify the number of u32 entries needed in child nodes. | ||
7 | Should set to 1. | ||
8 | - size-cells: specify number of u32 entries needed to specify child nodes size | ||
9 | in reg property. Should set to 1. | ||
10 | - ranges: describes the address mapping of a memory-mapped bus. Should set to | ||
11 | physical address map of child's base address, physical address within | ||
12 | parent's address space and length of the address map. For am33xx, | ||
13 | 3 set of child register maps present, ECAP register space, EQEP | ||
14 | register space, EHRPWM register space. | ||
15 | |||
16 | Also child nodes should also populated under PWMSS DT node. | ||
17 | |||
18 | Example: | ||
19 | pwmss0: pwmss@48300000 { | ||
20 | compatible = "ti,am33xx-pwmss"; | ||
21 | reg = <0x48300000 0x10>; | ||
22 | ti,hwmods = "epwmss0"; | ||
23 | #address-cells = <1>; | ||
24 | #size-cells = <1>; | ||
25 | status = "disabled"; | ||
26 | ranges = <0x48300100 0x48300100 0x80 /* ECAP */ | ||
27 | 0x48300180 0x48300180 0x80 /* EQEP */ | ||
28 | 0x48300200 0x48300200 0x80>; /* EHRPWM */ | ||
29 | |||
30 | /* child nodes go here */ | ||
31 | }; | ||
diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt index 73ec962bfe8c..06e67247859a 100644 --- a/Documentation/devicetree/bindings/pwm/pwm.txt +++ b/Documentation/devicetree/bindings/pwm/pwm.txt | |||
@@ -37,10 +37,21 @@ device: | |||
37 | pwm-names = "backlight"; | 37 | pwm-names = "backlight"; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | Note that in the example above, specifying the "pwm-names" is redundant | ||
41 | because the name "backlight" would be used as fallback anyway. | ||
42 | |||
40 | pwm-specifier typically encodes the chip-relative PWM number and the PWM | 43 | pwm-specifier typically encodes the chip-relative PWM number and the PWM |
41 | period in nanoseconds. Note that in the example above, specifying the | 44 | period in nanoseconds. |
42 | "pwm-names" is redundant because the name "backlight" would be used as | 45 | |
43 | fallback anyway. | 46 | Optionally, the pwm-specifier can encode a number of flags in a third cell: |
47 | - bit 0: PWM signal polarity (0: normal polarity, 1: inverse polarity) | ||
48 | |||
49 | Example with optional PWM specifier for inverse polarity | ||
50 | |||
51 | bl: backlight { | ||
52 | pwms = <&pwm 0 5000000 1>; | ||
53 | pwm-names = "backlight"; | ||
54 | }; | ||
44 | 55 | ||
45 | 2) PWM controller nodes | 56 | 2) PWM controller nodes |
46 | ----------------------- | 57 | ----------------------- |
diff --git a/Documentation/devicetree/bindings/pwm/spear-pwm.txt b/Documentation/devicetree/bindings/pwm/spear-pwm.txt new file mode 100644 index 000000000000..3ac779d83386 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/spear-pwm.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | == ST SPEAr SoC PWM controller == | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be one of: | ||
5 | - "st,spear320-pwm" | ||
6 | - "st,spear1340-pwm" | ||
7 | - reg: physical base address and length of the controller's registers | ||
8 | - #pwm-cells: number of cells used to specify PWM which is fixed to 2 on | ||
9 | SPEAr. The first cell specifies the per-chip index of the PWM to use and | ||
10 | the second cell is the period in nanoseconds. | ||
11 | |||
12 | Example: | ||
13 | |||
14 | pwm: pwm@a8000000 { | ||
15 | compatible ="st,spear320-pwm"; | ||
16 | reg = <0xa8000000 0x1000>; | ||
17 | #pwm-cells = <2>; | ||
18 | }; | ||
diff --git a/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt b/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt new file mode 100644 index 000000000000..2943ee5fce00 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/ti,twl-pwm.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | Texas Instruments TWL series PWM drivers | ||
2 | |||
3 | Supported PWMs: | ||
4 | On TWL4030 series: PWM1 and PWM2 | ||
5 | On TWL6030 series: PWM0 and PWM1 | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: "ti,twl4030-pwm" or "ti,twl6030-pwm" | ||
9 | - #pwm-cells: should be 2. The first cell specifies the per-chip index | ||
10 | of the PWM to use and the second cell is the period in nanoseconds. | ||
11 | |||
12 | Example: | ||
13 | |||
14 | twl_pwm: pwm { | ||
15 | compatible = "ti,twl6030-pwm"; | ||
16 | #pwm-cells = <2>; | ||
17 | }; | ||
diff --git a/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt b/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt new file mode 100644 index 000000000000..cb64f3acc10f --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/ti,twl-pwmled.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | Texas Instruments TWL series PWM drivers connected to LED terminals | ||
2 | |||
3 | Supported PWMs: | ||
4 | On TWL4030 series: PWMA and PWMB (connected to LEDA and LEDB terminals) | ||
5 | On TWL6030 series: LED PWM (mainly used as charging indicator LED) | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: "ti,twl4030-pwmled" or "ti,twl6030-pwmled" | ||
9 | - #pwm-cells: should be 2. The first cell specifies the per-chip index | ||
10 | of the PWM to use and the second cell is the period in nanoseconds. | ||
11 | |||
12 | Example: | ||
13 | |||
14 | twl_pwmled: pwmled { | ||
15 | compatible = "ti,twl6030-pwmled"; | ||
16 | #pwm-cells = <2>; | ||
17 | }; | ||
diff --git a/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt new file mode 100644 index 000000000000..bcc63678a9a5 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/vt8500-pwm.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | VIA/Wondermedia VT8500/WM8xxx series SoC PWM controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "via,vt8500-pwm" | ||
5 | - reg: physical base address and length of the controller's registers | ||
6 | - #pwm-cells: should be 2. The first cell specifies the per-chip index | ||
7 | of the PWM to use and the second cell is the period in nanoseconds. | ||
8 | - clocks: phandle to the PWM source clock | ||
9 | |||
10 | Example: | ||
11 | |||
12 | pwm1: pwm@d8220000 { | ||
13 | #pwm-cells = <2>; | ||
14 | compatible = "via,vt8500-pwm"; | ||
15 | reg = <0xd8220000 0x1000>; | ||
16 | clocks = <&clkpwm>; | ||
17 | }; | ||
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt index 8cf24f6f0a99..7b53da5cb75b 100644 --- a/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt +++ b/Documentation/devicetree/bindings/spi/nvidia,tegra20-sflash.txt | |||
@@ -13,7 +13,7 @@ Recommended properties: | |||
13 | 13 | ||
14 | Example: | 14 | Example: |
15 | 15 | ||
16 | spi@7000d600 { | 16 | spi@7000c380 { |
17 | compatible = "nvidia,tegra20-sflash"; | 17 | compatible = "nvidia,tegra20-sflash"; |
18 | reg = <0x7000c380 0x80>; | 18 | reg = <0x7000c380 0x80>; |
19 | interrupts = <0 39 0x04>; | 19 | interrupts = <0 39 0x04>; |
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt index f5b1ad1a1ec3..eefe15e3d95e 100644 --- a/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt +++ b/Documentation/devicetree/bindings/spi/nvidia,tegra20-slink.txt | |||
@@ -13,7 +13,7 @@ Recommended properties: | |||
13 | 13 | ||
14 | Example: | 14 | Example: |
15 | 15 | ||
16 | slink@7000d600 { | 16 | spi@7000d600 { |
17 | compatible = "nvidia,tegra20-slink"; | 17 | compatible = "nvidia,tegra20-slink"; |
18 | reg = <0x7000d600 0x200>; | 18 | reg = <0x7000d600 0x200>; |
19 | interrupts = <0 82 0x04>; | 19 | interrupts = <0 82 0x04>; |
diff --git a/Documentation/devicetree/bindings/spi/spi_atmel.txt b/Documentation/devicetree/bindings/spi/spi_atmel.txt new file mode 100644 index 000000000000..07e04cdc0c9e --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi_atmel.txt | |||
@@ -0,0 +1,26 @@ | |||
1 | Atmel SPI device | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : should be "atmel,at91rm9200-spi". | ||
5 | - reg: Address and length of the register set for the device | ||
6 | - interrupts: Should contain spi interrupt | ||
7 | - cs-gpios: chipselects | ||
8 | |||
9 | Example: | ||
10 | |||
11 | spi1: spi@fffcc000 { | ||
12 | compatible = "atmel,at91rm9200-spi"; | ||
13 | reg = <0xfffcc000 0x4000>; | ||
14 | interrupts = <13 4 5>; | ||
15 | #address-cells = <1>; | ||
16 | #size-cells = <0>; | ||
17 | cs-gpios = <&pioB 3 0>; | ||
18 | status = "okay"; | ||
19 | |||
20 | mmc-slot@0 { | ||
21 | compatible = "mmc-spi-slot"; | ||
22 | reg = <0>; | ||
23 | gpios = <&pioC 4 0>; /* CD */ | ||
24 | spi-max-frequency = <25000000>; | ||
25 | }; | ||
26 | }; | ||
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index f15cb74c4f78..406d82d5d2bb 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt | |||
@@ -373,7 +373,7 @@ Protocol: 2.00+ | |||
373 | 1 Loadlin | 373 | 1 Loadlin |
374 | 2 bootsect-loader (0x20, all other values reserved) | 374 | 2 bootsect-loader (0x20, all other values reserved) |
375 | 3 Syslinux | 375 | 3 Syslinux |
376 | 4 Etherboot/gPXE | 376 | 4 Etherboot/gPXE/iPXE |
377 | 5 ELILO | 377 | 5 ELILO |
378 | 7 GRUB | 378 | 7 GRUB |
379 | 8 U-Boot | 379 | 8 U-Boot |
@@ -381,6 +381,7 @@ Protocol: 2.00+ | |||
381 | A Gujin | 381 | A Gujin |
382 | B Qemu | 382 | B Qemu |
383 | C Arcturus Networks uCbootloader | 383 | C Arcturus Networks uCbootloader |
384 | D kexec-tools | ||
384 | E Extended (see ext_loader_type) | 385 | E Extended (see ext_loader_type) |
385 | F Special (0xFF = undefined) | 386 | F Special (0xFF = undefined) |
386 | 10 Reserved | 387 | 10 Reserved |
diff --git a/Documentation/xtensa/atomctl.txt b/Documentation/xtensa/atomctl.txt new file mode 100644 index 000000000000..10a8d1ff35ec --- /dev/null +++ b/Documentation/xtensa/atomctl.txt | |||
@@ -0,0 +1,44 @@ | |||
1 | We Have Atomic Operation Control (ATOMCTL) Register. | ||
2 | This register determines the effect of using a S32C1I instruction | ||
3 | with various combinations of: | ||
4 | |||
5 | 1. With and without an Coherent Cache Controller which | ||
6 | can do Atomic Transactions to the memory internally. | ||
7 | |||
8 | 2. With and without An Intelligent Memory Controller which | ||
9 | can do Atomic Transactions itself. | ||
10 | |||
11 | The Core comes up with a default value of for the three types of cache ops: | ||
12 | |||
13 | 0x28: (WB: Internal, WT: Internal, BY:Exception) | ||
14 | |||
15 | On the FPGA Cards we typically simulate an Intelligent Memory controller | ||
16 | which can implement RCW transactions. For FPGA cards with an External | ||
17 | Memory controller we let it to the atomic operations internally while | ||
18 | doing a Cached (WB) transaction and use the Memory RCW for un-cached | ||
19 | operations. | ||
20 | |||
21 | For systems without an coherent cache controller, non-MX, we always | ||
22 | use the memory controllers RCW, thought non-MX controlers likely | ||
23 | support the Internal Operation. | ||
24 | |||
25 | CUSTOMER-WARNING: | ||
26 | Virtually all customers buy their memory controllers from vendors that | ||
27 | don't support atomic RCW memory transactions and will likely want to | ||
28 | configure this register to not use RCW. | ||
29 | |||
30 | Developers might find using RCW in Bypass mode convenient when testing | ||
31 | with the cache being bypassed; for example studying cache alias problems. | ||
32 | |||
33 | See Section 4.3.12.4 of ISA; Bits: | ||
34 | |||
35 | WB WT BY | ||
36 | 5 4 | 3 2 | 1 0 | ||
37 | 2 Bit | ||
38 | Field | ||
39 | Values WB - Write Back WT - Write Thru BY - Bypass | ||
40 | --------- --------------- ----------------- ---------------- | ||
41 | 0 Exception Exception Exception | ||
42 | 1 RCW Transaction RCW Transaction RCW Transaction | ||
43 | 2 Internal Operation Exception Reserved | ||
44 | 3 Reserved Reserved Reserved | ||
@@ -981,6 +981,12 @@ _modinst_post: _modinst_ | |||
981 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst | 981 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst |
982 | $(call cmd,depmod) | 982 | $(call cmd,depmod) |
983 | 983 | ||
984 | ifeq ($(CONFIG_MODULE_SIG), y) | ||
985 | PHONY += modules_sign | ||
986 | modules_sign: | ||
987 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign | ||
988 | endif | ||
989 | |||
984 | else # CONFIG_MODULES | 990 | else # CONFIG_MODULES |
985 | 991 | ||
986 | # Modules not configured | 992 | # Modules not configured |
diff --git a/arch/Kconfig b/arch/Kconfig index 54ffd0f9df21..8e9e3246b2b4 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -113,6 +113,25 @@ config HAVE_EFFICIENT_UNALIGNED_ACCESS | |||
113 | See Documentation/unaligned-memory-access.txt for more | 113 | See Documentation/unaligned-memory-access.txt for more |
114 | information on the topic of unaligned memory accesses. | 114 | information on the topic of unaligned memory accesses. |
115 | 115 | ||
116 | config ARCH_USE_BUILTIN_BSWAP | ||
117 | bool | ||
118 | help | ||
119 | Modern versions of GCC (since 4.4) have builtin functions | ||
120 | for handling byte-swapping. Using these, instead of the old | ||
121 | inline assembler that the architecture code provides in the | ||
122 | __arch_bswapXX() macros, allows the compiler to see what's | ||
123 | happening and offers more opportunity for optimisation. In | ||
124 | particular, the compiler will be able to combine the byteswap | ||
125 | with a nearby load or store and use load-and-swap or | ||
126 | store-and-swap instructions if the architecture has them. It | ||
127 | should almost *never* result in code which is worse than the | ||
128 | hand-coded assembler in <asm/swab.h>. But just in case it | ||
129 | does, the use of the builtins is optional. | ||
130 | |||
131 | Any architecture with load-and-swap or store-and-swap | ||
132 | instructions should set this. And it shouldn't hurt to set it | ||
133 | on architectures that don't have such instructions. | ||
134 | |||
116 | config HAVE_SYSCALL_WRAPPERS | 135 | config HAVE_SYSCALL_WRAPPERS |
117 | bool | 136 | bool |
118 | 137 | ||
diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi index 009096d1d2c3..b4ca60f4eb42 100644 --- a/arch/arm/boot/dts/spear13xx.dtsi +++ b/arch/arm/boot/dts/spear13xx.dtsi | |||
@@ -73,7 +73,7 @@ | |||
73 | 400000 | 73 | 400000 |
74 | 500000 | 74 | 500000 |
75 | 600000 >; | 75 | 600000 >; |
76 | status = "disable"; | 76 | status = "disabled"; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | ahb { | 79 | ahb { |
@@ -118,15 +118,15 @@ | |||
118 | compatible = "st,spear600-fsmc-nand"; | 118 | compatible = "st,spear600-fsmc-nand"; |
119 | #address-cells = <1>; | 119 | #address-cells = <1>; |
120 | #size-cells = <1>; | 120 | #size-cells = <1>; |
121 | reg = <0xb0000000 0x1000 /* FSMC Register */ | 121 | reg = <0xb0000000 0x1000 /* FSMC Register*/ |
122 | 0xb0800000 0x0010>; /* NAND Base */ | 122 | 0xb0800000 0x0010 /* NAND Base DATA */ |
123 | reg-names = "fsmc_regs", "nand_data"; | 123 | 0xb0820000 0x0010 /* NAND Base ADDR */ |
124 | 0xb0810000 0x0010>; /* NAND Base CMD */ | ||
125 | reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd"; | ||
124 | interrupts = <0 20 0x4 | 126 | interrupts = <0 20 0x4 |
125 | 0 21 0x4 | 127 | 0 21 0x4 |
126 | 0 22 0x4 | 128 | 0 22 0x4 |
127 | 0 23 0x4>; | 129 | 0 23 0x4>; |
128 | st,ale-off = <0x20000>; | ||
129 | st,cle-off = <0x10000>; | ||
130 | st,mode = <2>; | 130 | st,mode = <2>; |
131 | status = "disabled"; | 131 | status = "disabled"; |
132 | }; | 132 | }; |
@@ -144,7 +144,7 @@ | |||
144 | compatible = "st,pcm-audio"; | 144 | compatible = "st,pcm-audio"; |
145 | #address-cells = <0>; | 145 | #address-cells = <0>; |
146 | #size-cells = <0>; | 146 | #size-cells = <0>; |
147 | status = "disable"; | 147 | status = "disabled"; |
148 | }; | 148 | }; |
149 | 149 | ||
150 | smi: flash@ea000000 { | 150 | smi: flash@ea000000 { |
diff --git a/arch/arm/boot/dts/spear300.dtsi b/arch/arm/boot/dts/spear300.dtsi index 090adc656015..f79b3dfaabe6 100644 --- a/arch/arm/boot/dts/spear300.dtsi +++ b/arch/arm/boot/dts/spear300.dtsi | |||
@@ -38,10 +38,10 @@ | |||
38 | #address-cells = <1>; | 38 | #address-cells = <1>; |
39 | #size-cells = <1>; | 39 | #size-cells = <1>; |
40 | reg = <0x94000000 0x1000 /* FSMC Register */ | 40 | reg = <0x94000000 0x1000 /* FSMC Register */ |
41 | 0x80000000 0x0010>; /* NAND Base */ | 41 | 0x80000000 0x0010 /* NAND Base DATA */ |
42 | reg-names = "fsmc_regs", "nand_data"; | 42 | 0x80020000 0x0010 /* NAND Base ADDR */ |
43 | st,ale-off = <0x20000>; | 43 | 0x80010000 0x0010>; /* NAND Base CMD */ |
44 | st,cle-off = <0x10000>; | 44 | reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd"; |
45 | status = "disabled"; | 45 | status = "disabled"; |
46 | }; | 46 | }; |
47 | 47 | ||
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi index e814e5e97083..ab45b8c81982 100644 --- a/arch/arm/boot/dts/spear310.dtsi +++ b/arch/arm/boot/dts/spear310.dtsi | |||
@@ -33,10 +33,10 @@ | |||
33 | #address-cells = <1>; | 33 | #address-cells = <1>; |
34 | #size-cells = <1>; | 34 | #size-cells = <1>; |
35 | reg = <0x44000000 0x1000 /* FSMC Register */ | 35 | reg = <0x44000000 0x1000 /* FSMC Register */ |
36 | 0x40000000 0x0010>; /* NAND Base */ | 36 | 0x40000000 0x0010 /* NAND Base DATA */ |
37 | reg-names = "fsmc_regs", "nand_data"; | 37 | 0x40020000 0x0010 /* NAND Base ADDR */ |
38 | st,ale-off = <0x10000>; | 38 | 0x40010000 0x0010>; /* NAND Base CMD */ |
39 | st,cle-off = <0x20000>; | 39 | reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd"; |
40 | status = "disabled"; | 40 | status = "disabled"; |
41 | }; | 41 | }; |
42 | 42 | ||
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi index c056a84deabf..caa5520b1fd4 100644 --- a/arch/arm/boot/dts/spear320.dtsi +++ b/arch/arm/boot/dts/spear320.dtsi | |||
@@ -40,10 +40,10 @@ | |||
40 | #address-cells = <1>; | 40 | #address-cells = <1>; |
41 | #size-cells = <1>; | 41 | #size-cells = <1>; |
42 | reg = <0x4c000000 0x1000 /* FSMC Register */ | 42 | reg = <0x4c000000 0x1000 /* FSMC Register */ |
43 | 0x50000000 0x0010>; /* NAND Base */ | 43 | 0x50000000 0x0010 /* NAND Base DATA */ |
44 | reg-names = "fsmc_regs", "nand_data"; | 44 | 0x50020000 0x0010 /* NAND Base ADDR */ |
45 | st,ale-off = <0x20000>; | 45 | 0x50010000 0x0010>; /* NAND Base CMD */ |
46 | st,cle-off = <0x10000>; | 46 | reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd"; |
47 | status = "disabled"; | 47 | status = "disabled"; |
48 | }; | 48 | }; |
49 | 49 | ||
diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi index e051dde5181f..19f99dc4115e 100644 --- a/arch/arm/boot/dts/spear600.dtsi +++ b/arch/arm/boot/dts/spear600.dtsi | |||
@@ -76,10 +76,10 @@ | |||
76 | #address-cells = <1>; | 76 | #address-cells = <1>; |
77 | #size-cells = <1>; | 77 | #size-cells = <1>; |
78 | reg = <0xd1800000 0x1000 /* FSMC Register */ | 78 | reg = <0xd1800000 0x1000 /* FSMC Register */ |
79 | 0xd2000000 0x4000>; /* NAND Base */ | 79 | 0xd2000000 0x0010 /* NAND Base DATA */ |
80 | reg-names = "fsmc_regs", "nand_data"; | 80 | 0xd2020000 0x0010 /* NAND Base ADDR */ |
81 | st,ale-off = <0x20000>; | 81 | 0xd2010000 0x0010>; /* NAND Base CMD */ |
82 | st,cle-off = <0x10000>; | 82 | reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd"; |
83 | status = "disabled"; | 83 | status = "disabled"; |
84 | }; | 84 | }; |
85 | 85 | ||
diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig index 240b25eea565..86cfd2959c47 100644 --- a/arch/arm/configs/nhk8815_defconfig +++ b/arch/arm/configs/nhk8815_defconfig | |||
@@ -57,7 +57,7 @@ CONFIG_MTD_CHAR=y | |||
57 | CONFIG_MTD_BLOCK=y | 57 | CONFIG_MTD_BLOCK=y |
58 | CONFIG_MTD_NAND=y | 58 | CONFIG_MTD_NAND=y |
59 | CONFIG_MTD_NAND_ECC_SMC=y | 59 | CONFIG_MTD_NAND_ECC_SMC=y |
60 | CONFIG_MTD_NAND_NOMADIK=y | 60 | CONFIG_MTD_NAND_FSMC=y |
61 | CONFIG_MTD_ONENAND=y | 61 | CONFIG_MTD_ONENAND=y |
62 | CONFIG_MTD_ONENAND_VERIFY_WRITE=y | 62 | CONFIG_MTD_ONENAND_VERIFY_WRITE=y |
63 | CONFIG_MTD_ONENAND_GENERIC=y | 63 | CONFIG_MTD_ONENAND_GENERIC=y |
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h index ac03bdb4ae44..4da7cde70b5d 100644 --- a/arch/arm/include/uapi/asm/unistd.h +++ b/arch/arm/include/uapi/asm/unistd.h | |||
@@ -405,6 +405,7 @@ | |||
405 | #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) | 405 | #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) |
406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) | 406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) |
407 | /* 378 for kcmp */ | 407 | /* 378 for kcmp */ |
408 | #define __NR_finit_module (__NR_SYSCALL_BASE+379) | ||
408 | 409 | ||
409 | /* | 410 | /* |
410 | * This may need to be greater than __NR_last_syscall+1 in order to | 411 | * This may need to be greater than __NR_last_syscall+1 in order to |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 5935b6a02e6e..a4fda4e7a372 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -388,6 +388,7 @@ | |||
388 | CALL(sys_process_vm_readv) | 388 | CALL(sys_process_vm_readv) |
389 | CALL(sys_process_vm_writev) | 389 | CALL(sys_process_vm_writev) |
390 | CALL(sys_ni_syscall) /* reserved for sys_kcmp */ | 390 | CALL(sys_ni_syscall) /* reserved for sys_kcmp */ |
391 | CALL(sys_finit_module) | ||
391 | #ifndef syscalls_counted | 392 | #ifndef syscalls_counted |
392 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls | 393 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls |
393 | #define syscalls_counted | 394 | #define syscalls_counted |
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index 5ccdf53c5a9d..98167a4319f7 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
20 | #include <linux/mtd/mtd.h> | 20 | #include <linux/mtd/mtd.h> |
21 | #include <linux/mtd/nand.h> | 21 | #include <linux/mtd/nand.h> |
22 | #include <linux/mtd/fsmc.h> | ||
22 | #include <linux/mtd/onenand.h> | 23 | #include <linux/mtd/onenand.h> |
23 | #include <linux/mtd/partitions.h> | 24 | #include <linux/mtd/partitions.h> |
24 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
@@ -33,7 +34,6 @@ | |||
33 | #include <asm/mach/arch.h> | 34 | #include <asm/mach/arch.h> |
34 | #include <asm/mach/flash.h> | 35 | #include <asm/mach/flash.h> |
35 | #include <asm/mach/time.h> | 36 | #include <asm/mach/time.h> |
36 | #include <mach/fsmc.h> | ||
37 | #include <mach/irqs.h> | 37 | #include <mach/irqs.h> |
38 | 38 | ||
39 | #include "cpu-8815.h" | 39 | #include "cpu-8815.h" |
@@ -42,39 +42,34 @@ | |||
42 | #define SRC_CR_INIT_MASK 0x00007fff | 42 | #define SRC_CR_INIT_MASK 0x00007fff |
43 | #define SRC_CR_INIT_VAL 0x2aaa8000 | 43 | #define SRC_CR_INIT_VAL 0x2aaa8000 |
44 | 44 | ||
45 | #define ALE_OFF 0x1000000 | ||
46 | #define CLE_OFF 0x800000 | ||
47 | |||
45 | /* These addresses span 16MB, so use three individual pages */ | 48 | /* These addresses span 16MB, so use three individual pages */ |
46 | static struct resource nhk8815_nand_resources[] = { | 49 | static struct resource nhk8815_nand_resources[] = { |
47 | { | 50 | { |
51 | .name = "nand_data", | ||
52 | .start = 0x40000000, | ||
53 | .end = 0x40000000 + SZ_16K - 1, | ||
54 | .flags = IORESOURCE_MEM, | ||
55 | }, { | ||
48 | .name = "nand_addr", | 56 | .name = "nand_addr", |
49 | .start = NAND_IO_ADDR, | 57 | .start = 0x40000000 + ALE_OFF, |
50 | .end = NAND_IO_ADDR + 0xfff, | 58 | .end = 0x40000000 +ALE_OFF + SZ_16K - 1, |
51 | .flags = IORESOURCE_MEM, | 59 | .flags = IORESOURCE_MEM, |
52 | }, { | 60 | }, { |
53 | .name = "nand_cmd", | 61 | .name = "nand_cmd", |
54 | .start = NAND_IO_CMD, | 62 | .start = 0x40000000 + CLE_OFF, |
55 | .end = NAND_IO_CMD + 0xfff, | 63 | .end = 0x40000000 + CLE_OFF + SZ_16K - 1, |
56 | .flags = IORESOURCE_MEM, | 64 | .flags = IORESOURCE_MEM, |
57 | }, { | 65 | }, { |
58 | .name = "nand_data", | 66 | .name = "fsmc_regs", |
59 | .start = NAND_IO_DATA, | 67 | .start = NOMADIK_FSMC_BASE, |
60 | .end = NAND_IO_DATA + 0xfff, | 68 | .end = NOMADIK_FSMC_BASE + SZ_4K - 1, |
61 | .flags = IORESOURCE_MEM, | 69 | .flags = IORESOURCE_MEM, |
62 | } | 70 | }, |
63 | }; | 71 | }; |
64 | 72 | ||
65 | static int nhk8815_nand_init(void) | ||
66 | { | ||
67 | /* FSMC setup for nand chip select (8-bit nand in 8815NHK) */ | ||
68 | writel(0x0000000E, FSMC_PCR(0)); | ||
69 | writel(0x000D0A00, FSMC_PMEM(0)); | ||
70 | writel(0x00100A00, FSMC_PATT(0)); | ||
71 | |||
72 | /* enable access to the chip select area */ | ||
73 | writel(readl(FSMC_PCR(0)) | 0x04, FSMC_PCR(0)); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | /* | 73 | /* |
79 | * These partitions are the same as those used in the 2.6.20 release | 74 | * These partitions are the same as those used in the 2.6.20 release |
80 | * shipped by the vendor; the first two partitions are mandated | 75 | * shipped by the vendor; the first two partitions are mandated |
@@ -108,20 +103,28 @@ static struct mtd_partition nhk8815_partitions[] = { | |||
108 | } | 103 | } |
109 | }; | 104 | }; |
110 | 105 | ||
111 | static struct nomadik_nand_platform_data nhk8815_nand_data = { | 106 | static struct fsmc_nand_timings nhk8815_nand_timings = { |
112 | .parts = nhk8815_partitions, | 107 | .thiz = 0, |
113 | .nparts = ARRAY_SIZE(nhk8815_partitions), | 108 | .thold = 0x10, |
114 | .options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING, | 109 | .twait = 0x0A, |
115 | .init = nhk8815_nand_init, | 110 | .tset = 0, |
111 | }; | ||
112 | |||
113 | static struct fsmc_nand_platform_data nhk8815_nand_platform_data = { | ||
114 | .nand_timings = &nhk8815_nand_timings, | ||
115 | .partitions = nhk8815_partitions, | ||
116 | .nr_partitions = ARRAY_SIZE(nhk8815_partitions), | ||
117 | .width = FSMC_NAND_BW8, | ||
116 | }; | 118 | }; |
117 | 119 | ||
118 | static struct platform_device nhk8815_nand_device = { | 120 | static struct platform_device nhk8815_nand_device = { |
119 | .name = "nomadik_nand", | 121 | .name = "fsmc-nand", |
120 | .dev = { | 122 | .id = -1, |
121 | .platform_data = &nhk8815_nand_data, | 123 | .resource = nhk8815_nand_resources, |
124 | .num_resources = ARRAY_SIZE(nhk8815_nand_resources), | ||
125 | .dev = { | ||
126 | .platform_data = &nhk8815_nand_platform_data, | ||
122 | }, | 127 | }, |
123 | .resource = nhk8815_nand_resources, | ||
124 | .num_resources = ARRAY_SIZE(nhk8815_nand_resources), | ||
125 | }; | 128 | }; |
126 | 129 | ||
127 | /* These are the partitions for the OneNand device, different from above */ | 130 | /* These are the partitions for the OneNand device, different from above */ |
@@ -176,6 +179,10 @@ static struct platform_device nhk8815_onenand_device = { | |||
176 | .num_resources = ARRAY_SIZE(nhk8815_onenand_resource), | 179 | .num_resources = ARRAY_SIZE(nhk8815_onenand_resource), |
177 | }; | 180 | }; |
178 | 181 | ||
182 | /* bus control reg. and bus timing reg. for CS0..CS3 */ | ||
183 | #define FSMC_BCR(x) (NOMADIK_FSMC_VA + (x << 3)) | ||
184 | #define FSMC_BTR(x) (NOMADIK_FSMC_VA + (x << 3) + 0x04) | ||
185 | |||
179 | static void __init nhk8815_onenand_init(void) | 186 | static void __init nhk8815_onenand_init(void) |
180 | { | 187 | { |
181 | #ifdef CONFIG_MTD_ONENAND | 188 | #ifdef CONFIG_MTD_ONENAND |
diff --git a/arch/arm/mach-nomadik/include/mach/fsmc.h b/arch/arm/mach-nomadik/include/mach/fsmc.h deleted file mode 100644 index 8c2c05183685..000000000000 --- a/arch/arm/mach-nomadik/include/mach/fsmc.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | |||
2 | /* Definitions for the Nomadik FSMC "Flexible Static Memory controller" */ | ||
3 | |||
4 | #ifndef __ASM_ARCH_FSMC_H | ||
5 | #define __ASM_ARCH_FSMC_H | ||
6 | |||
7 | #include <mach/hardware.h> | ||
8 | /* | ||
9 | * Register list | ||
10 | */ | ||
11 | |||
12 | /* bus control reg. and bus timing reg. for CS0..CS3 */ | ||
13 | #define FSMC_BCR(x) (NOMADIK_FSMC_VA + (x << 3)) | ||
14 | #define FSMC_BTR(x) (NOMADIK_FSMC_VA + (x << 3) + 0x04) | ||
15 | |||
16 | /* PC-card and NAND: | ||
17 | * PCR = control register | ||
18 | * PMEM = memory timing | ||
19 | * PATT = attribute timing | ||
20 | * PIO = I/O timing | ||
21 | * PECCR = ECC result | ||
22 | */ | ||
23 | #define FSMC_PCR(x) (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x00) | ||
24 | #define FSMC_PMEM(x) (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x08) | ||
25 | #define FSMC_PATT(x) (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x0c) | ||
26 | #define FSMC_PIO(x) (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x10) | ||
27 | #define FSMC_PECCR(x) (NOMADIK_FSMC_VA + ((2 + x) << 5) + 0x14) | ||
28 | |||
29 | #endif /* __ASM_ARCH_FSMC_H */ | ||
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 60529e0b3d67..cf07e289b4ea 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c | |||
@@ -256,6 +256,11 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = { | |||
256 | }, | 256 | }, |
257 | }; | 257 | }; |
258 | 258 | ||
259 | static struct platform_device rx51_battery_device = { | ||
260 | .name = "rx51-battery", | ||
261 | .id = -1, | ||
262 | }; | ||
263 | |||
259 | static void rx51_charger_set_power(bool on) | 264 | static void rx51_charger_set_power(bool on) |
260 | { | 265 | { |
261 | gpio_set_value(RX51_USB_TRANSCEIVER_RST_GPIO, on); | 266 | gpio_set_value(RX51_USB_TRANSCEIVER_RST_GPIO, on); |
@@ -277,6 +282,7 @@ static void __init rx51_charger_init(void) | |||
277 | WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO, | 282 | WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO, |
278 | GPIOF_OUT_INIT_HIGH, "isp1704_reset")); | 283 | GPIOF_OUT_INIT_HIGH, "isp1704_reset")); |
279 | 284 | ||
285 | platform_device_register(&rx51_battery_device); | ||
280 | platform_device_register(&rx51_charger_device); | 286 | platform_device_register(&rx51_charger_device); |
281 | } | 287 | } |
282 | 288 | ||
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 12f3994c43db..8b204ae69002 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c | |||
@@ -250,6 +250,18 @@ static struct resource rtc_resources[] = { | |||
250 | */ | 250 | */ |
251 | static struct resource fsmc_resources[] = { | 251 | static struct resource fsmc_resources[] = { |
252 | { | 252 | { |
253 | .name = "nand_addr", | ||
254 | .start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE, | ||
255 | .end = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE + SZ_16K - 1, | ||
256 | .flags = IORESOURCE_MEM, | ||
257 | }, | ||
258 | { | ||
259 | .name = "nand_cmd", | ||
260 | .start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE, | ||
261 | .end = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE + SZ_16K - 1, | ||
262 | .flags = IORESOURCE_MEM, | ||
263 | }, | ||
264 | { | ||
253 | .name = "nand_data", | 265 | .name = "nand_data", |
254 | .start = U300_NAND_CS0_PHYS_BASE, | 266 | .start = U300_NAND_CS0_PHYS_BASE, |
255 | .end = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1, | 267 | .end = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1, |
@@ -1492,8 +1504,6 @@ static struct fsmc_nand_platform_data nand_platform_data = { | |||
1492 | .nr_partitions = ARRAY_SIZE(u300_partitions), | 1504 | .nr_partitions = ARRAY_SIZE(u300_partitions), |
1493 | .options = NAND_SKIP_BBTSCAN, | 1505 | .options = NAND_SKIP_BBTSCAN, |
1494 | .width = FSMC_NAND_BW8, | 1506 | .width = FSMC_NAND_BW8, |
1495 | .ale_off = PLAT_NAND_ALE, | ||
1496 | .cle_off = PLAT_NAND_CLE, | ||
1497 | }; | 1507 | }; |
1498 | 1508 | ||
1499 | static struct platform_device nand_device = { | 1509 | static struct platform_device nand_device = { |
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c index 37400f5869e6..51123f985eb5 100644 --- a/arch/cris/kernel/module.c +++ b/arch/cris/kernel/module.c | |||
@@ -32,8 +32,6 @@ | |||
32 | #ifdef CONFIG_ETRAX_KMALLOCED_MODULES | 32 | #ifdef CONFIG_ETRAX_KMALLOCED_MODULES |
33 | void *module_alloc(unsigned long size) | 33 | void *module_alloc(unsigned long size) |
34 | { | 34 | { |
35 | if (size == 0) | ||
36 | return NULL; | ||
37 | return kmalloc(size, GFP_KERNEL); | 35 | return kmalloc(size, GFP_KERNEL); |
38 | } | 36 | } |
39 | 37 | ||
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 5e34ccf39a49..2a625fb063e1 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
@@ -214,8 +214,6 @@ static inline int reassemble_22(int as22) | |||
214 | 214 | ||
215 | void *module_alloc(unsigned long size) | 215 | void *module_alloc(unsigned long size) |
216 | { | 216 | { |
217 | if (size == 0) | ||
218 | return NULL; | ||
219 | /* using RWX means less protection for modules, but it's | 217 | /* using RWX means less protection for modules, but it's |
220 | * easier than trying to map the text, data, init_text and | 218 | * easier than trying to map the text, data, init_text and |
221 | * init_data correctly */ | 219 | * init_data correctly */ |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index cec8aae5cbf8..97909d3b1d7b 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
@@ -356,3 +356,4 @@ COMPAT_SYS_SPU(sendmmsg) | |||
356 | SYSCALL_SPU(setns) | 356 | SYSCALL_SPU(setns) |
357 | COMPAT_SYS(process_vm_readv) | 357 | COMPAT_SYS(process_vm_readv) |
358 | COMPAT_SYS(process_vm_writev) | 358 | COMPAT_SYS(process_vm_writev) |
359 | SYSCALL(finit_module) | ||
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index bcbbe413c606..29365e15ed7c 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <uapi/asm/unistd.h> | 12 | #include <uapi/asm/unistd.h> |
13 | 13 | ||
14 | 14 | ||
15 | #define __NR_syscalls 353 | 15 | #define __NR_syscalls 354 |
16 | 16 | ||
17 | #define __NR__exit __NR_exit | 17 | #define __NR__exit __NR_exit |
18 | #define NR_syscalls __NR_syscalls | 18 | #define NR_syscalls __NR_syscalls |
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index 380b5d37a904..8c478c6c6b1e 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h | |||
@@ -375,6 +375,7 @@ | |||
375 | #define __NR_setns 350 | 375 | #define __NR_setns 350 |
376 | #define __NR_process_vm_readv 351 | 376 | #define __NR_process_vm_readv 351 |
377 | #define __NR_process_vm_writev 352 | 377 | #define __NR_process_vm_writev 352 |
378 | #define __NR_finit_module 353 | ||
378 | 379 | ||
379 | 380 | ||
380 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ | 381 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ |
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index f1ddc0d23679..4435488ebe25 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c | |||
@@ -43,10 +43,6 @@ void *module_alloc(unsigned long size) | |||
43 | { | 43 | { |
44 | void *ret; | 44 | void *ret; |
45 | 45 | ||
46 | /* We handle the zero case fine, unlike vmalloc */ | ||
47 | if (size == 0) | ||
48 | return NULL; | ||
49 | |||
50 | ret = module_map(size); | 46 | ret = module_map(size); |
51 | if (ret) | 47 | if (ret) |
52 | memset(ret, 0, size); | 48 | memset(ret, 0, size); |
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index 243ffebe38d6..4918d91bc3a6 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c | |||
@@ -42,8 +42,6 @@ void *module_alloc(unsigned long size) | |||
42 | int i = 0; | 42 | int i = 0; |
43 | int npages; | 43 | int npages; |
44 | 44 | ||
45 | if (size == 0) | ||
46 | return NULL; | ||
47 | npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; | 45 | npages = (size + PAGE_SIZE - 1) / PAGE_SIZE; |
48 | pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); | 46 | pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL); |
49 | if (pages == NULL) | 47 | if (pages == NULL) |
diff --git a/arch/unicore32/kernel/module.c b/arch/unicore32/kernel/module.c index 8fbe8577f5e6..16bd1495b934 100644 --- a/arch/unicore32/kernel/module.c +++ b/arch/unicore32/kernel/module.c | |||
@@ -27,9 +27,6 @@ void *module_alloc(unsigned long size) | |||
27 | struct vm_struct *area; | 27 | struct vm_struct *area; |
28 | 28 | ||
29 | size = PAGE_ALIGN(size); | 29 | size = PAGE_ALIGN(size); |
30 | if (!size) | ||
31 | return NULL; | ||
32 | |||
33 | area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); | 30 | area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); |
34 | if (!area) | 31 | if (!area) |
35 | return NULL; | 32 | return NULL; |
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index fbd895562292..3286a92e662a 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c | |||
@@ -26,11 +26,6 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, | |||
26 | #ifdef CONFIG_X86_32 | 26 | #ifdef CONFIG_X86_32 |
27 | static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) | 27 | static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) |
28 | { | 28 | { |
29 | /* | ||
30 | * We use exception 16 if we have hardware math and we've either seen | ||
31 | * it or the CPU claims it is internal | ||
32 | */ | ||
33 | int fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu); | ||
34 | seq_printf(m, | 29 | seq_printf(m, |
35 | "fdiv_bug\t: %s\n" | 30 | "fdiv_bug\t: %s\n" |
36 | "hlt_bug\t\t: %s\n" | 31 | "hlt_bug\t\t: %s\n" |
@@ -45,7 +40,7 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) | |||
45 | c->f00f_bug ? "yes" : "no", | 40 | c->f00f_bug ? "yes" : "no", |
46 | c->coma_bug ? "yes" : "no", | 41 | c->coma_bug ? "yes" : "no", |
47 | c->hard_math ? "yes" : "no", | 42 | c->hard_math ? "yes" : "no", |
48 | fpu_exception ? "yes" : "no", | 43 | c->hard_math ? "yes" : "no", |
49 | c->cpuid_level, | 44 | c->cpuid_level, |
50 | c->wp_works_ok ? "yes" : "no"); | 45 | c->wp_works_ok ? "yes" : "no"); |
51 | } | 46 | } |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 6e03b0d69138..7dc4e459c2b3 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -42,39 +42,6 @@ | |||
42 | * (these are usually mapped into the 0x30-0xff vector range) | 42 | * (these are usually mapped into the 0x30-0xff vector range) |
43 | */ | 43 | */ |
44 | 44 | ||
45 | #ifdef CONFIG_X86_32 | ||
46 | /* | ||
47 | * Note that on a 486, we don't want to do a SIGFPE on an irq13 | ||
48 | * as the irq is unreliable, and exception 16 works correctly | ||
49 | * (ie as explained in the intel literature). On a 386, you | ||
50 | * can't use exception 16 due to bad IBM design, so we have to | ||
51 | * rely on the less exact irq13. | ||
52 | * | ||
53 | * Careful.. Not only is IRQ13 unreliable, but it is also | ||
54 | * leads to races. IBM designers who came up with it should | ||
55 | * be shot. | ||
56 | */ | ||
57 | |||
58 | static irqreturn_t math_error_irq(int cpl, void *dev_id) | ||
59 | { | ||
60 | outb(0, 0xF0); | ||
61 | if (ignore_fpu_irq || !boot_cpu_data.hard_math) | ||
62 | return IRQ_NONE; | ||
63 | math_error(get_irq_regs(), 0, X86_TRAP_MF); | ||
64 | return IRQ_HANDLED; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * New motherboards sometimes make IRQ 13 be a PCI interrupt, | ||
69 | * so allow interrupt sharing. | ||
70 | */ | ||
71 | static struct irqaction fpu_irq = { | ||
72 | .handler = math_error_irq, | ||
73 | .name = "fpu", | ||
74 | .flags = IRQF_NO_THREAD, | ||
75 | }; | ||
76 | #endif | ||
77 | |||
78 | /* | 45 | /* |
79 | * IRQ2 is cascade interrupt to second interrupt controller | 46 | * IRQ2 is cascade interrupt to second interrupt controller |
80 | */ | 47 | */ |
@@ -242,13 +209,6 @@ void __init native_init_IRQ(void) | |||
242 | setup_irq(2, &irq2); | 209 | setup_irq(2, &irq2); |
243 | 210 | ||
244 | #ifdef CONFIG_X86_32 | 211 | #ifdef CONFIG_X86_32 |
245 | /* | ||
246 | * External FPU? Set up irq13 if so, for | ||
247 | * original braindamaged IBM FERR coupling. | ||
248 | */ | ||
249 | if (boot_cpu_data.hard_math && !cpu_has_fpu) | ||
250 | setup_irq(FPU_IRQ, &fpu_irq); | ||
251 | |||
252 | irq_ctx_init(smp_processor_id()); | 212 | irq_ctx_init(smp_processor_id()); |
253 | #endif | 213 | #endif |
254 | } | 214 | } |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index eb8586693e0b..ecffca11f4e9 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -69,9 +69,6 @@ | |||
69 | 69 | ||
70 | asmlinkage int system_call(void); | 70 | asmlinkage int system_call(void); |
71 | 71 | ||
72 | /* Do we ignore FPU interrupts ? */ | ||
73 | char ignore_fpu_irq; | ||
74 | |||
75 | /* | 72 | /* |
76 | * The IDT has to be page-aligned to simplify the Pentium | 73 | * The IDT has to be page-aligned to simplify the Pentium |
77 | * F0 0F bug workaround. | 74 | * F0 0F bug workaround. |
@@ -564,9 +561,6 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr) | |||
564 | 561 | ||
565 | dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) | 562 | dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) |
566 | { | 563 | { |
567 | #ifdef CONFIG_X86_32 | ||
568 | ignore_fpu_irq = 1; | ||
569 | #endif | ||
570 | exception_enter(regs); | 564 | exception_enter(regs); |
571 | math_error(regs, error_code, X86_TRAP_MF); | 565 | math_error(regs, error_code, X86_TRAP_MF); |
572 | exception_exit(regs); | 566 | exception_exit(regs); |
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index ee3c220ee500..05f404f53f59 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl | |||
@@ -356,3 +356,4 @@ | |||
356 | 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv | 356 | 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv |
357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev | 357 | 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev |
358 | 349 i386 kcmp sys_kcmp | 358 | 349 i386 kcmp sys_kcmp |
359 | 350 i386 finit_module sys_finit_module | ||
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index a582bfed95bb..7c58c84b7bc8 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl | |||
@@ -319,6 +319,7 @@ | |||
319 | 310 64 process_vm_readv sys_process_vm_readv | 319 | 310 64 process_vm_readv sys_process_vm_readv |
320 | 311 64 process_vm_writev sys_process_vm_writev | 320 | 311 64 process_vm_writev sys_process_vm_writev |
321 | 312 common kcmp sys_kcmp | 321 | 312 common kcmp sys_kcmp |
322 | 313 common finit_module sys_finit_module | ||
322 | 323 | ||
323 | # | 324 | # |
324 | # x32-specific system call numbers start at 512 to avoid cache impact | 325 | # x32-specific system call numbers start at 512 to avoid cache impact |
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 2481f267be29..73d34e77c39c 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
@@ -17,6 +17,7 @@ config XTENSA | |||
17 | select GENERIC_KERNEL_EXECVE | 17 | select GENERIC_KERNEL_EXECVE |
18 | select ARCH_WANT_OPTIONAL_GPIOLIB | 18 | select ARCH_WANT_OPTIONAL_GPIOLIB |
19 | select CLONE_BACKWARDS | 19 | select CLONE_BACKWARDS |
20 | select IRQ_DOMAIN | ||
20 | help | 21 | help |
21 | Xtensa processors are 32-bit RISC machines designed by Tensilica | 22 | Xtensa processors are 32-bit RISC machines designed by Tensilica |
22 | primarily for embedded systems. These processors are both | 23 | primarily for embedded systems. These processors are both |
@@ -150,6 +151,15 @@ config XTENSA_PLATFORM_S6105 | |||
150 | select SERIAL_CONSOLE | 151 | select SERIAL_CONSOLE |
151 | select NO_IOPORT | 152 | select NO_IOPORT |
152 | 153 | ||
154 | config XTENSA_PLATFORM_XTFPGA | ||
155 | bool "XTFPGA" | ||
156 | select SERIAL_CONSOLE | ||
157 | select ETHOC | ||
158 | select XTENSA_CALIBRATE_CCOUNT | ||
159 | help | ||
160 | XTFPGA is the name of Tensilica board family (LX60, LX110, LX200, ML605). | ||
161 | This hardware is capable of running a full Linux distribution. | ||
162 | |||
153 | endchoice | 163 | endchoice |
154 | 164 | ||
155 | 165 | ||
@@ -177,6 +187,17 @@ config CMDLINE | |||
177 | time by entering them here. As a minimum, you should specify the | 187 | time by entering them here. As a minimum, you should specify the |
178 | memory size and the root device (e.g., mem=64M root=/dev/nfs). | 188 | memory size and the root device (e.g., mem=64M root=/dev/nfs). |
179 | 189 | ||
190 | config USE_OF | ||
191 | bool "Flattened Device Tree support" | ||
192 | select OF | ||
193 | select OF_EARLY_FLATTREE | ||
194 | help | ||
195 | Include support for flattened device tree machine descriptions. | ||
196 | |||
197 | config BUILTIN_DTB | ||
198 | string "DTB to build into the kernel image" | ||
199 | depends on OF | ||
200 | |||
180 | source "mm/Kconfig" | 201 | source "mm/Kconfig" |
181 | 202 | ||
182 | source "drivers/pcmcia/Kconfig" | 203 | source "drivers/pcmcia/Kconfig" |
diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug index 11c585295dd7..a34010e0e51c 100644 --- a/arch/xtensa/Kconfig.debug +++ b/arch/xtensa/Kconfig.debug | |||
@@ -2,6 +2,26 @@ menu "Kernel hacking" | |||
2 | 2 | ||
3 | source "lib/Kconfig.debug" | 3 | source "lib/Kconfig.debug" |
4 | 4 | ||
5 | endmenu | 5 | config LD_NO_RELAX |
6 | bool "Disable linker relaxation" | ||
7 | default n | ||
8 | help | ||
9 | Enable this function to disable link-time optimizations. | ||
10 | The default linker behavior is to combine identical literal | ||
11 | values to reduce code size and remove unnecessary overhead from | ||
12 | assembler-generated 'longcall' sequences. | ||
13 | Enabling this option improves the link time but increases the | ||
14 | code size, and possibly execution time. | ||
15 | |||
16 | config S32C1I_SELFTEST | ||
17 | bool "Perform S32C1I instruction self-test at boot" | ||
18 | default y | ||
19 | help | ||
20 | Enable this option to test S32C1I instruction behavior at boot. | ||
21 | Correct operation of this instruction requires some cooperation from hardware | ||
22 | external to the processor (such as bus bridge, bus fabric, or memory controller). | ||
23 | It is easy to make wrong hardware configuration, this test should catch it early. | ||
6 | 24 | ||
25 | Say 'N' on stable hardware. | ||
7 | 26 | ||
27 | endmenu | ||
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index bb5ba61723f7..0aa72702f179 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile | |||
@@ -38,6 +38,7 @@ endif | |||
38 | platform-$(CONFIG_XTENSA_PLATFORM_XT2000) := xt2000 | 38 | platform-$(CONFIG_XTENSA_PLATFORM_XT2000) := xt2000 |
39 | platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss | 39 | platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss |
40 | platform-$(CONFIG_XTENSA_PLATFORM_S6105) := s6105 | 40 | platform-$(CONFIG_XTENSA_PLATFORM_S6105) := s6105 |
41 | platform-$(CONFIG_XTENSA_PLATFORM_XTFPGA) := xtfpga | ||
41 | 42 | ||
42 | PLATFORM = $(platform-y) | 43 | PLATFORM = $(platform-y) |
43 | export PLATFORM | 44 | export PLATFORM |
@@ -49,6 +50,17 @@ KBUILD_CFLAGS += -pipe -mlongcalls | |||
49 | 50 | ||
50 | KBUILD_CFLAGS += $(call cc-option,-mforce-no-pic,) | 51 | KBUILD_CFLAGS += $(call cc-option,-mforce-no-pic,) |
51 | 52 | ||
53 | ifneq ($(CONFIG_LD_NO_RELAX),) | ||
54 | LDFLAGS := --no-relax | ||
55 | endif | ||
56 | |||
57 | ifeq ($(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#"),1) | ||
58 | CHECKFLAGS += -D__XTENSA_EB__ | ||
59 | endif | ||
60 | ifeq ($(shell echo -e __XTENSA_EL__ | $(CC) -E - | grep -v "\#"),1) | ||
61 | CHECKFLAGS += -D__XTENSA_EL__ | ||
62 | endif | ||
63 | |||
52 | vardirs := $(patsubst %,arch/xtensa/variants/%/,$(variant-y)) | 64 | vardirs := $(patsubst %,arch/xtensa/variants/%/,$(variant-y)) |
53 | plfdirs := $(patsubst %,arch/xtensa/platforms/%/,$(platform-y)) | 65 | plfdirs := $(patsubst %,arch/xtensa/platforms/%/,$(platform-y)) |
54 | 66 | ||
@@ -75,6 +87,10 @@ core-y += $(buildvar) $(buildplf) | |||
75 | 87 | ||
76 | libs-y += arch/xtensa/lib/ $(LIBGCC) | 88 | libs-y += arch/xtensa/lib/ $(LIBGCC) |
77 | 89 | ||
90 | ifneq ($(CONFIG_BUILTIN_DTB),"") | ||
91 | core-$(CONFIG_OF) += arch/xtensa/boot/ | ||
92 | endif | ||
93 | |||
78 | boot := arch/xtensa/boot | 94 | boot := arch/xtensa/boot |
79 | 95 | ||
80 | all: zImage | 96 | all: zImage |
@@ -84,7 +100,9 @@ bzImage : zImage | |||
84 | zImage: vmlinux | 100 | zImage: vmlinux |
85 | $(Q)$(MAKE) $(build)=$(boot) $@ | 101 | $(Q)$(MAKE) $(build)=$(boot) $@ |
86 | 102 | ||
103 | %.dtb: | ||
104 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ | ||
105 | |||
87 | define archhelp | 106 | define archhelp |
88 | @echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)' | 107 | @echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)' |
89 | endef | 108 | endef |
90 | |||
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile index 4018f8994196..818647e815d7 100644 --- a/arch/xtensa/boot/Makefile +++ b/arch/xtensa/boot/Makefile | |||
@@ -22,12 +22,35 @@ subdir-y := lib | |||
22 | # Subdirs for the boot loader(s) | 22 | # Subdirs for the boot loader(s) |
23 | 23 | ||
24 | bootdir-$(CONFIG_XTENSA_PLATFORM_ISS) += boot-elf | 24 | bootdir-$(CONFIG_XTENSA_PLATFORM_ISS) += boot-elf |
25 | bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf | 25 | bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf boot-uboot |
26 | bootdir-$(CONFIG_XTENSA_PLATFORM_XTFPGA) += boot-redboot boot-elf boot-uboot | ||
26 | 27 | ||
27 | 28 | ||
29 | BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o | ||
30 | ifneq ($(CONFIG_BUILTIN_DTB),"") | ||
31 | obj-$(CONFIG_OF) += $(BUILTIN_DTB) | ||
32 | endif | ||
33 | |||
34 | # Rule to build device tree blobs | ||
35 | $(obj)/%.dtb: $(src)/dts/%.dts FORCE | ||
36 | $(call if_changed_dep,dtc) | ||
37 | |||
38 | clean-files := *.dtb.S | ||
39 | |||
28 | zImage Image: $(bootdir-y) | 40 | zImage Image: $(bootdir-y) |
29 | 41 | ||
30 | $(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \ | 42 | $(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \ |
31 | $(addprefix $(obj)/,$(host-progs)) | 43 | $(addprefix $(obj)/,$(host-progs)) |
32 | $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS) | 44 | $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS) |
33 | 45 | ||
46 | OBJCOPYFLAGS = --strip-all -R .comment -R .note.gnu.build-id -O binary | ||
47 | |||
48 | vmlinux.bin: vmlinux FORCE | ||
49 | $(call if_changed,objcopy) | ||
50 | |||
51 | vmlinux.bin.gz: vmlinux.bin FORCE | ||
52 | $(call if_changed,gzip) | ||
53 | |||
54 | boot-elf: vmlinux.bin | ||
55 | boot-redboot: vmlinux.bin.gz | ||
56 | boot-uboot: vmlinux.bin.gz | ||
diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile index f10992b89027..1fe01b78c124 100644 --- a/arch/xtensa/boot/boot-elf/Makefile +++ b/arch/xtensa/boot/boot-elf/Makefile | |||
@@ -4,9 +4,6 @@ | |||
4 | # for more details. | 4 | # for more details. |
5 | # | 5 | # |
6 | 6 | ||
7 | GZIP = gzip | ||
8 | GZIP_FLAGS = -v9fc | ||
9 | |||
10 | ifeq ($(BIG_ENDIAN),1) | 7 | ifeq ($(BIG_ENDIAN),1) |
11 | OBJCOPY_ARGS := -O elf32-xtensa-be | 8 | OBJCOPY_ARGS := -O elf32-xtensa-be |
12 | else | 9 | else |
@@ -20,18 +17,17 @@ boot-y := bootstrap.o | |||
20 | 17 | ||
21 | OBJS := $(addprefix $(obj)/,$(boot-y)) | 18 | OBJS := $(addprefix $(obj)/,$(boot-y)) |
22 | 19 | ||
23 | vmlinux.tmp: vmlinux | 20 | $(obj)/Image.o: vmlinux.bin $(OBJS) |
24 | $(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \ | 21 | $(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ |
25 | $^ $@ | 22 | --add-section image=vmlinux.bin \ |
26 | |||
27 | Image: vmlinux.tmp $(OBJS) arch/$(ARCH)/boot/boot-elf/boot.lds | ||
28 | $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ | ||
29 | --add-section image=vmlinux.tmp \ | ||
30 | --set-section-flags image=contents,alloc,load,load,data \ | 23 | --set-section-flags image=contents,alloc,load,load,data \ |
31 | $(OBJS) $@.tmp | 24 | $(OBJS) $@ |
32 | $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \ | ||
33 | -T arch/$(ARCH)/boot/boot-elf/boot.lds \ | ||
34 | -o arch/$(ARCH)/boot/$@.elf $@.tmp | ||
35 | 25 | ||
36 | zImage: Image | 26 | $(obj)/../Image.elf: $(obj)/Image.o $(obj)/boot.lds |
27 | $(Q)$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \ | ||
28 | -T $(obj)/boot.lds \ | ||
29 | --build-id=none \ | ||
30 | -o $@ $(obj)/Image.o | ||
31 | $(Q)$(kecho) ' Kernel: $@ is ready' | ||
37 | 32 | ||
33 | zImage: $(obj)/../Image.elf | ||
diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile index 25a78c6b1530..8be8b9436981 100644 --- a/arch/xtensa/boot/boot-redboot/Makefile +++ b/arch/xtensa/boot/boot-redboot/Makefile | |||
@@ -4,8 +4,6 @@ | |||
4 | # for more details. | 4 | # for more details. |
5 | # | 5 | # |
6 | 6 | ||
7 | GZIP = gzip | ||
8 | GZIP_FLAGS = -v9fc | ||
9 | ifeq ($(BIG_ENDIAN),1) | 7 | ifeq ($(BIG_ENDIAN),1) |
10 | OBJCOPY_ARGS := -O elf32-xtensa-be | 8 | OBJCOPY_ARGS := -O elf32-xtensa-be |
11 | else | 9 | else |
@@ -21,17 +19,17 @@ LIBS := arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a | |||
21 | 19 | ||
22 | LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) | 20 | LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) |
23 | 21 | ||
24 | vmlinux.tmp: vmlinux | 22 | $(obj)/zImage.o: vmlinux.bin.gz $(OBJS) |
25 | $(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \ | 23 | $(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ |
26 | $^ $@ | 24 | --add-section image=vmlinux.bin.gz \ |
25 | --set-section-flags image=contents,alloc,load,load,data \ | ||
26 | $(OBJS) $@ | ||
27 | 27 | ||
28 | vmlinux.tmp.gz: vmlinux.tmp | 28 | $(obj)/zImage.elf: $(obj)/zImage.o $(LIBS) |
29 | $(GZIP) $(GZIP_FLAGS) $^ > $@ | 29 | $(Q)$(LD) $(LD_ARGS) -o $@ $^ -L/xtensa-elf/lib $(LIBGCC) |
30 | 30 | ||
31 | zImage: vmlinux.tmp.gz $(OBJS) $(LIBS) | 31 | $(obj)/../zImage.redboot: $(obj)/zImage.elf |
32 | $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ | 32 | $(Q)$(OBJCOPY) -S -O binary $< $@ |
33 | --add-section image=vmlinux.tmp.gz \ | 33 | $(Q)$(kecho) ' Kernel: $@ is ready' |
34 | --set-section-flags image=contents,alloc,load,load,data \ | 34 | |
35 | $(OBJS) $@.tmp | 35 | zImage: $(obj)/../zImage.redboot |
36 | $(LD) $(LD_ARGS) -o $@.elf $@.tmp $(LIBS) -L/xtensa-elf/lib $(LIBGCC) | ||
37 | $(OBJCOPY) -S -O binary $@.elf arch/$(ARCH)/boot/$@.redboot | ||
diff --git a/arch/xtensa/boot/boot-uboot/Makefile b/arch/xtensa/boot/boot-uboot/Makefile new file mode 100644 index 000000000000..bfbf8af582f1 --- /dev/null +++ b/arch/xtensa/boot/boot-uboot/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # | ||
2 | # This file is subject to the terms and conditions of the GNU General Public | ||
3 | # License. See the file "COPYING" in the main directory of this archive | ||
4 | # for more details. | ||
5 | # | ||
6 | |||
7 | UIMAGE_LOADADDR = 0xd0001000 | ||
8 | UIMAGE_COMPRESSION = gzip | ||
9 | |||
10 | $(obj)/../uImage: vmlinux.bin.gz FORCE | ||
11 | $(call if_changed,uimage) | ||
12 | $(Q)$(kecho) ' Kernel: $@ is ready' | ||
13 | |||
14 | zImage: $(obj)/../uImage | ||
diff --git a/arch/xtensa/boot/dts/lx60.dts b/arch/xtensa/boot/dts/lx60.dts new file mode 100644 index 000000000000..2eab3658e1bd --- /dev/null +++ b/arch/xtensa/boot/dts/lx60.dts | |||
@@ -0,0 +1,11 @@ | |||
1 | /dts-v1/; | ||
2 | /include/ "xtfpga.dtsi" | ||
3 | /include/ "xtfpga-flash-4m.dtsi" | ||
4 | |||
5 | / { | ||
6 | compatible = "xtensa,lx60"; | ||
7 | memory@0 { | ||
8 | device_type = "memory"; | ||
9 | reg = <0x00000000 0x04000000>; | ||
10 | }; | ||
11 | }; | ||
diff --git a/arch/xtensa/boot/dts/ml605.dts b/arch/xtensa/boot/dts/ml605.dts new file mode 100644 index 000000000000..6ed51d6554e6 --- /dev/null +++ b/arch/xtensa/boot/dts/ml605.dts | |||
@@ -0,0 +1,11 @@ | |||
1 | /dts-v1/; | ||
2 | /include/ "xtfpga.dtsi" | ||
3 | /include/ "xtfpga-flash-16m.dtsi" | ||
4 | |||
5 | / { | ||
6 | compatible = "xtensa,ml605"; | ||
7 | memory@0 { | ||
8 | device_type = "memory"; | ||
9 | reg = <0x00000000 0x08000000>; | ||
10 | }; | ||
11 | }; | ||
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi new file mode 100644 index 000000000000..e5703c7beeb6 --- /dev/null +++ b/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi | |||
@@ -0,0 +1,26 @@ | |||
1 | / { | ||
2 | flash: flash@f8000000 { | ||
3 | #address-cells = <1>; | ||
4 | #size-cells = <1>; | ||
5 | compatible = "cfi-flash"; | ||
6 | reg = <0xf8000000 0x01000000>; | ||
7 | bank-width = <2>; | ||
8 | device-width = <2>; | ||
9 | partition@0x0 { | ||
10 | label = "boot loader area"; | ||
11 | reg = <0x00000000 0x00400000>; | ||
12 | }; | ||
13 | partition@0x400000 { | ||
14 | label = "kernel image"; | ||
15 | reg = <0x00400000 0x00600000>; | ||
16 | }; | ||
17 | partition@0xa00000 { | ||
18 | label = "data"; | ||
19 | reg = <0x00a00000 0x005e0000>; | ||
20 | }; | ||
21 | partition@0xfe0000 { | ||
22 | label = "boot environment"; | ||
23 | reg = <0x00fe0000 0x00020000>; | ||
24 | }; | ||
25 | }; | ||
26 | }; | ||
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi new file mode 100644 index 000000000000..6f9c10d6b689 --- /dev/null +++ b/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi | |||
@@ -0,0 +1,18 @@ | |||
1 | / { | ||
2 | flash: flash@f8000000 { | ||
3 | #address-cells = <1>; | ||
4 | #size-cells = <1>; | ||
5 | compatible = "cfi-flash"; | ||
6 | reg = <0xf8000000 0x00400000>; | ||
7 | bank-width = <2>; | ||
8 | device-width = <2>; | ||
9 | partition@0x0 { | ||
10 | label = "boot loader area"; | ||
11 | reg = <0x00000000 0x003f0000>; | ||
12 | }; | ||
13 | partition@0x3f0000 { | ||
14 | label = "boot environment"; | ||
15 | reg = <0x003f0000 0x00010000>; | ||
16 | }; | ||
17 | }; | ||
18 | }; | ||
diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi new file mode 100644 index 000000000000..7eda6ecf7eef --- /dev/null +++ b/arch/xtensa/boot/dts/xtfpga.dtsi | |||
@@ -0,0 +1,56 @@ | |||
1 | / { | ||
2 | compatible = "xtensa,xtfpga"; | ||
3 | #address-cells = <1>; | ||
4 | #size-cells = <1>; | ||
5 | interrupt-parent = <&pic>; | ||
6 | |||
7 | chosen { | ||
8 | bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug"; | ||
9 | }; | ||
10 | |||
11 | memory@0 { | ||
12 | device_type = "memory"; | ||
13 | reg = <0x00000000 0x06000000>; | ||
14 | }; | ||
15 | |||
16 | cpus { | ||
17 | #address-cells = <1>; | ||
18 | #size-cells = <0>; | ||
19 | cpu@0 { | ||
20 | compatible = "xtensa,cpu"; | ||
21 | reg = <0>; | ||
22 | /* Filled in by platform_setup from FPGA register | ||
23 | * clock-frequency = <100000000>; | ||
24 | */ | ||
25 | }; | ||
26 | }; | ||
27 | |||
28 | pic: pic { | ||
29 | compatible = "xtensa,pic"; | ||
30 | /* one cell: internal irq number, | ||
31 | * two cells: second cell == 0: internal irq number | ||
32 | * second cell == 1: external irq number | ||
33 | */ | ||
34 | #interrupt-cells = <2>; | ||
35 | interrupt-controller; | ||
36 | }; | ||
37 | |||
38 | serial0: serial@fd050020 { | ||
39 | device_type = "serial"; | ||
40 | compatible = "ns16550a"; | ||
41 | no-loopback-test; | ||
42 | reg = <0xfd050020 0x20>; | ||
43 | reg-shift = <2>; | ||
44 | interrupts = <0 1>; /* external irq 0 */ | ||
45 | /* Filled in by platform_setup from FPGA register | ||
46 | * clock-frequency = <100000000>; | ||
47 | */ | ||
48 | }; | ||
49 | |||
50 | enet0: ethoc@fd030000 { | ||
51 | compatible = "opencores,ethoc"; | ||
52 | reg = <0xfd030000 0x4000 0xfd800000 0x4000>; | ||
53 | interrupts = <1 1>; /* external irq 1 */ | ||
54 | local-mac-address = [00 50 c2 13 6f 00]; | ||
55 | }; | ||
56 | }; | ||
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index 24f50cada70c..c3f289174c10 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h | |||
@@ -66,19 +66,35 @@ | |||
66 | */ | 66 | */ |
67 | static inline void atomic_add(int i, atomic_t * v) | 67 | static inline void atomic_add(int i, atomic_t * v) |
68 | { | 68 | { |
69 | unsigned int vval; | 69 | #if XCHAL_HAVE_S32C1I |
70 | 70 | unsigned long tmp; | |
71 | __asm__ __volatile__( | 71 | int result; |
72 | "rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 72 | |
73 | "l32i %0, %2, 0 \n\t" | 73 | __asm__ __volatile__( |
74 | "add %0, %0, %1 \n\t" | 74 | "1: l32i %1, %3, 0\n" |
75 | "s32i %0, %2, 0 \n\t" | 75 | " wsr %1, scompare1\n" |
76 | "wsr a15, ps \n\t" | 76 | " add %0, %1, %2\n" |
77 | "rsync \n" | 77 | " s32c1i %0, %3, 0\n" |
78 | : "=&a" (vval) | 78 | " bne %0, %1, 1b\n" |
79 | : "a" (i), "a" (v) | 79 | : "=&a" (result), "=&a" (tmp) |
80 | : "a15", "memory" | 80 | : "a" (i), "a" (v) |
81 | ); | 81 | : "memory" |
82 | ); | ||
83 | #else | ||
84 | unsigned int vval; | ||
85 | |||
86 | __asm__ __volatile__( | ||
87 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
88 | " l32i %0, %2, 0\n" | ||
89 | " add %0, %0, %1\n" | ||
90 | " s32i %0, %2, 0\n" | ||
91 | " wsr a15, ps\n" | ||
92 | " rsync\n" | ||
93 | : "=&a" (vval) | ||
94 | : "a" (i), "a" (v) | ||
95 | : "a15", "memory" | ||
96 | ); | ||
97 | #endif | ||
82 | } | 98 | } |
83 | 99 | ||
84 | /** | 100 | /** |
@@ -90,19 +106,35 @@ static inline void atomic_add(int i, atomic_t * v) | |||
90 | */ | 106 | */ |
91 | static inline void atomic_sub(int i, atomic_t *v) | 107 | static inline void atomic_sub(int i, atomic_t *v) |
92 | { | 108 | { |
93 | unsigned int vval; | 109 | #if XCHAL_HAVE_S32C1I |
94 | 110 | unsigned long tmp; | |
95 | __asm__ __volatile__( | 111 | int result; |
96 | "rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 112 | |
97 | "l32i %0, %2, 0 \n\t" | 113 | __asm__ __volatile__( |
98 | "sub %0, %0, %1 \n\t" | 114 | "1: l32i %1, %3, 0\n" |
99 | "s32i %0, %2, 0 \n\t" | 115 | " wsr %1, scompare1\n" |
100 | "wsr a15, ps \n\t" | 116 | " sub %0, %1, %2\n" |
101 | "rsync \n" | 117 | " s32c1i %0, %3, 0\n" |
102 | : "=&a" (vval) | 118 | " bne %0, %1, 1b\n" |
103 | : "a" (i), "a" (v) | 119 | : "=&a" (result), "=&a" (tmp) |
104 | : "a15", "memory" | 120 | : "a" (i), "a" (v) |
105 | ); | 121 | : "memory" |
122 | ); | ||
123 | #else | ||
124 | unsigned int vval; | ||
125 | |||
126 | __asm__ __volatile__( | ||
127 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
128 | " l32i %0, %2, 0\n" | ||
129 | " sub %0, %0, %1\n" | ||
130 | " s32i %0, %2, 0\n" | ||
131 | " wsr a15, ps\n" | ||
132 | " rsync\n" | ||
133 | : "=&a" (vval) | ||
134 | : "a" (i), "a" (v) | ||
135 | : "a15", "memory" | ||
136 | ); | ||
137 | #endif | ||
106 | } | 138 | } |
107 | 139 | ||
108 | /* | 140 | /* |
@@ -111,40 +143,78 @@ static inline void atomic_sub(int i, atomic_t *v) | |||
111 | 143 | ||
112 | static inline int atomic_add_return(int i, atomic_t * v) | 144 | static inline int atomic_add_return(int i, atomic_t * v) |
113 | { | 145 | { |
114 | unsigned int vval; | 146 | #if XCHAL_HAVE_S32C1I |
115 | 147 | unsigned long tmp; | |
116 | __asm__ __volatile__( | 148 | int result; |
117 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 149 | |
118 | "l32i %0, %2, 0 \n\t" | 150 | __asm__ __volatile__( |
119 | "add %0, %0, %1 \n\t" | 151 | "1: l32i %1, %3, 0\n" |
120 | "s32i %0, %2, 0 \n\t" | 152 | " wsr %1, scompare1\n" |
121 | "wsr a15, ps \n\t" | 153 | " add %0, %1, %2\n" |
122 | "rsync \n" | 154 | " s32c1i %0, %3, 0\n" |
123 | : "=&a" (vval) | 155 | " bne %0, %1, 1b\n" |
124 | : "a" (i), "a" (v) | 156 | " add %0, %0, %2\n" |
125 | : "a15", "memory" | 157 | : "=&a" (result), "=&a" (tmp) |
126 | ); | 158 | : "a" (i), "a" (v) |
127 | 159 | : "memory" | |
128 | return vval; | 160 | ); |
161 | |||
162 | return result; | ||
163 | #else | ||
164 | unsigned int vval; | ||
165 | |||
166 | __asm__ __volatile__( | ||
167 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
168 | " l32i %0, %2, 0\n" | ||
169 | " add %0, %0, %1\n" | ||
170 | " s32i %0, %2, 0\n" | ||
171 | " wsr a15, ps\n" | ||
172 | " rsync\n" | ||
173 | : "=&a" (vval) | ||
174 | : "a" (i), "a" (v) | ||
175 | : "a15", "memory" | ||
176 | ); | ||
177 | |||
178 | return vval; | ||
179 | #endif | ||
129 | } | 180 | } |
130 | 181 | ||
131 | static inline int atomic_sub_return(int i, atomic_t * v) | 182 | static inline int atomic_sub_return(int i, atomic_t * v) |
132 | { | 183 | { |
133 | unsigned int vval; | 184 | #if XCHAL_HAVE_S32C1I |
134 | 185 | unsigned long tmp; | |
135 | __asm__ __volatile__( | 186 | int result; |
136 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 187 | |
137 | "l32i %0, %2, 0 \n\t" | 188 | __asm__ __volatile__( |
138 | "sub %0, %0, %1 \n\t" | 189 | "1: l32i %1, %3, 0\n" |
139 | "s32i %0, %2, 0 \n\t" | 190 | " wsr %1, scompare1\n" |
140 | "wsr a15, ps \n\t" | 191 | " sub %0, %1, %2\n" |
141 | "rsync \n" | 192 | " s32c1i %0, %3, 0\n" |
142 | : "=&a" (vval) | 193 | " bne %0, %1, 1b\n" |
143 | : "a" (i), "a" (v) | 194 | " sub %0, %0, %2\n" |
144 | : "a15", "memory" | 195 | : "=&a" (result), "=&a" (tmp) |
145 | ); | 196 | : "a" (i), "a" (v) |
146 | 197 | : "memory" | |
147 | return vval; | 198 | ); |
199 | |||
200 | return result; | ||
201 | #else | ||
202 | unsigned int vval; | ||
203 | |||
204 | __asm__ __volatile__( | ||
205 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
206 | " l32i %0, %2, 0\n" | ||
207 | " sub %0, %0, %1\n" | ||
208 | " s32i %0, %2, 0\n" | ||
209 | " wsr a15, ps\n" | ||
210 | " rsync\n" | ||
211 | : "=&a" (vval) | ||
212 | : "a" (i), "a" (v) | ||
213 | : "a15", "memory" | ||
214 | ); | ||
215 | |||
216 | return vval; | ||
217 | #endif | ||
148 | } | 218 | } |
149 | 219 | ||
150 | /** | 220 | /** |
@@ -251,38 +321,70 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) | |||
251 | 321 | ||
252 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 322 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
253 | { | 323 | { |
254 | unsigned int all_f = -1; | 324 | #if XCHAL_HAVE_S32C1I |
255 | unsigned int vval; | 325 | unsigned long tmp; |
256 | 326 | int result; | |
257 | __asm__ __volatile__( | 327 | |
258 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 328 | __asm__ __volatile__( |
259 | "l32i %0, %2, 0 \n\t" | 329 | "1: l32i %1, %3, 0\n" |
260 | "xor %1, %4, %3 \n\t" | 330 | " wsr %1, scompare1\n" |
261 | "and %0, %0, %4 \n\t" | 331 | " and %0, %1, %2\n" |
262 | "s32i %0, %2, 0 \n\t" | 332 | " s32c1i %0, %3, 0\n" |
263 | "wsr a15, ps \n\t" | 333 | " bne %0, %1, 1b\n" |
264 | "rsync \n" | 334 | : "=&a" (result), "=&a" (tmp) |
265 | : "=&a" (vval), "=a" (mask) | 335 | : "a" (~mask), "a" (v) |
266 | : "a" (v), "a" (all_f), "1" (mask) | 336 | : "memory" |
267 | : "a15", "memory" | 337 | ); |
268 | ); | 338 | #else |
339 | unsigned int all_f = -1; | ||
340 | unsigned int vval; | ||
341 | |||
342 | __asm__ __volatile__( | ||
343 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
344 | " l32i %0, %2, 0\n" | ||
345 | " xor %1, %4, %3\n" | ||
346 | " and %0, %0, %4\n" | ||
347 | " s32i %0, %2, 0\n" | ||
348 | " wsr a15, ps\n" | ||
349 | " rsync\n" | ||
350 | : "=&a" (vval), "=a" (mask) | ||
351 | : "a" (v), "a" (all_f), "1" (mask) | ||
352 | : "a15", "memory" | ||
353 | ); | ||
354 | #endif | ||
269 | } | 355 | } |
270 | 356 | ||
271 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) | 357 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) |
272 | { | 358 | { |
273 | unsigned int vval; | 359 | #if XCHAL_HAVE_S32C1I |
274 | 360 | unsigned long tmp; | |
275 | __asm__ __volatile__( | 361 | int result; |
276 | "rsil a15,"__stringify(LOCKLEVEL)"\n\t" | 362 | |
277 | "l32i %0, %2, 0 \n\t" | 363 | __asm__ __volatile__( |
278 | "or %0, %0, %1 \n\t" | 364 | "1: l32i %1, %3, 0\n" |
279 | "s32i %0, %2, 0 \n\t" | 365 | " wsr %1, scompare1\n" |
280 | "wsr a15, ps \n\t" | 366 | " or %0, %1, %2\n" |
281 | "rsync \n" | 367 | " s32c1i %0, %3, 0\n" |
282 | : "=&a" (vval) | 368 | " bne %0, %1, 1b\n" |
283 | : "a" (mask), "a" (v) | 369 | : "=&a" (result), "=&a" (tmp) |
284 | : "a15", "memory" | 370 | : "a" (mask), "a" (v) |
285 | ); | 371 | : "memory" |
372 | ); | ||
373 | #else | ||
374 | unsigned int vval; | ||
375 | |||
376 | __asm__ __volatile__( | ||
377 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
378 | " l32i %0, %2, 0\n" | ||
379 | " or %0, %0, %1\n" | ||
380 | " s32i %0, %2, 0\n" | ||
381 | " wsr a15, ps\n" | ||
382 | " rsync\n" | ||
383 | : "=&a" (vval) | ||
384 | : "a" (mask), "a" (v) | ||
385 | : "a15", "memory" | ||
386 | ); | ||
387 | #endif | ||
286 | } | 388 | } |
287 | 389 | ||
288 | /* Atomic operations are already serializing */ | 390 | /* Atomic operations are already serializing */ |
@@ -294,4 +396,3 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v) | |||
294 | #endif /* __KERNEL__ */ | 396 | #endif /* __KERNEL__ */ |
295 | 397 | ||
296 | #endif /* _XTENSA_ATOMIC_H */ | 398 | #endif /* _XTENSA_ATOMIC_H */ |
297 | |||
diff --git a/arch/xtensa/include/asm/barrier.h b/arch/xtensa/include/asm/barrier.h index 55707a8009d3..ef021677d536 100644 --- a/arch/xtensa/include/asm/barrier.h +++ b/arch/xtensa/include/asm/barrier.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2001 - 2005 Tensilica Inc. | 6 | * Copyright (C) 2001 - 2012 Tensilica Inc. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _XTENSA_SYSTEM_H | 9 | #ifndef _XTENSA_SYSTEM_H |
@@ -12,8 +12,8 @@ | |||
12 | #define smp_read_barrier_depends() do { } while(0) | 12 | #define smp_read_barrier_depends() do { } while(0) |
13 | #define read_barrier_depends() do { } while(0) | 13 | #define read_barrier_depends() do { } while(0) |
14 | 14 | ||
15 | #define mb() barrier() | 15 | #define mb() ({ __asm__ __volatile__("memw" : : : "memory"); }) |
16 | #define rmb() mb() | 16 | #define rmb() barrier() |
17 | #define wmb() mb() | 17 | #define wmb() mb() |
18 | 18 | ||
19 | #ifdef CONFIG_SMP | 19 | #ifdef CONFIG_SMP |
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h index 5270197ddd36..84afe58d5d37 100644 --- a/arch/xtensa/include/asm/bitops.h +++ b/arch/xtensa/include/asm/bitops.h | |||
@@ -29,7 +29,6 @@ | |||
29 | #define smp_mb__before_clear_bit() barrier() | 29 | #define smp_mb__before_clear_bit() barrier() |
30 | #define smp_mb__after_clear_bit() barrier() | 30 | #define smp_mb__after_clear_bit() barrier() |
31 | 31 | ||
32 | #include <asm-generic/bitops/atomic.h> | ||
33 | #include <asm-generic/bitops/non-atomic.h> | 32 | #include <asm-generic/bitops/non-atomic.h> |
34 | 33 | ||
35 | #if XCHAL_HAVE_NSA | 34 | #if XCHAL_HAVE_NSA |
@@ -104,6 +103,132 @@ static inline unsigned long __fls(unsigned long word) | |||
104 | #endif | 103 | #endif |
105 | 104 | ||
106 | #include <asm-generic/bitops/fls64.h> | 105 | #include <asm-generic/bitops/fls64.h> |
106 | |||
107 | #if XCHAL_HAVE_S32C1I | ||
108 | |||
109 | static inline void set_bit(unsigned int bit, volatile unsigned long *p) | ||
110 | { | ||
111 | unsigned long tmp, value; | ||
112 | unsigned long mask = 1UL << (bit & 31); | ||
113 | |||
114 | p += bit >> 5; | ||
115 | |||
116 | __asm__ __volatile__( | ||
117 | "1: l32i %1, %3, 0\n" | ||
118 | " wsr %1, scompare1\n" | ||
119 | " or %0, %1, %2\n" | ||
120 | " s32c1i %0, %3, 0\n" | ||
121 | " bne %0, %1, 1b\n" | ||
122 | : "=&a" (tmp), "=&a" (value) | ||
123 | : "a" (mask), "a" (p) | ||
124 | : "memory"); | ||
125 | } | ||
126 | |||
127 | static inline void clear_bit(unsigned int bit, volatile unsigned long *p) | ||
128 | { | ||
129 | unsigned long tmp, value; | ||
130 | unsigned long mask = 1UL << (bit & 31); | ||
131 | |||
132 | p += bit >> 5; | ||
133 | |||
134 | __asm__ __volatile__( | ||
135 | "1: l32i %1, %3, 0\n" | ||
136 | " wsr %1, scompare1\n" | ||
137 | " and %0, %1, %2\n" | ||
138 | " s32c1i %0, %3, 0\n" | ||
139 | " bne %0, %1, 1b\n" | ||
140 | : "=&a" (tmp), "=&a" (value) | ||
141 | : "a" (~mask), "a" (p) | ||
142 | : "memory"); | ||
143 | } | ||
144 | |||
145 | static inline void change_bit(unsigned int bit, volatile unsigned long *p) | ||
146 | { | ||
147 | unsigned long tmp, value; | ||
148 | unsigned long mask = 1UL << (bit & 31); | ||
149 | |||
150 | p += bit >> 5; | ||
151 | |||
152 | __asm__ __volatile__( | ||
153 | "1: l32i %1, %3, 0\n" | ||
154 | " wsr %1, scompare1\n" | ||
155 | " xor %0, %1, %2\n" | ||
156 | " s32c1i %0, %3, 0\n" | ||
157 | " bne %0, %1, 1b\n" | ||
158 | : "=&a" (tmp), "=&a" (value) | ||
159 | : "a" (mask), "a" (p) | ||
160 | : "memory"); | ||
161 | } | ||
162 | |||
163 | static inline int | ||
164 | test_and_set_bit(unsigned int bit, volatile unsigned long *p) | ||
165 | { | ||
166 | unsigned long tmp, value; | ||
167 | unsigned long mask = 1UL << (bit & 31); | ||
168 | |||
169 | p += bit >> 5; | ||
170 | |||
171 | __asm__ __volatile__( | ||
172 | "1: l32i %1, %3, 0\n" | ||
173 | " wsr %1, scompare1\n" | ||
174 | " or %0, %1, %2\n" | ||
175 | " s32c1i %0, %3, 0\n" | ||
176 | " bne %0, %1, 1b\n" | ||
177 | : "=&a" (tmp), "=&a" (value) | ||
178 | : "a" (mask), "a" (p) | ||
179 | : "memory"); | ||
180 | |||
181 | return tmp & mask; | ||
182 | } | ||
183 | |||
184 | static inline int | ||
185 | test_and_clear_bit(unsigned int bit, volatile unsigned long *p) | ||
186 | { | ||
187 | unsigned long tmp, value; | ||
188 | unsigned long mask = 1UL << (bit & 31); | ||
189 | |||
190 | p += bit >> 5; | ||
191 | |||
192 | __asm__ __volatile__( | ||
193 | "1: l32i %1, %3, 0\n" | ||
194 | " wsr %1, scompare1\n" | ||
195 | " and %0, %1, %2\n" | ||
196 | " s32c1i %0, %3, 0\n" | ||
197 | " bne %0, %1, 1b\n" | ||
198 | : "=&a" (tmp), "=&a" (value) | ||
199 | : "a" (~mask), "a" (p) | ||
200 | : "memory"); | ||
201 | |||
202 | return tmp & mask; | ||
203 | } | ||
204 | |||
205 | static inline int | ||
206 | test_and_change_bit(unsigned int bit, volatile unsigned long *p) | ||
207 | { | ||
208 | unsigned long tmp, value; | ||
209 | unsigned long mask = 1UL << (bit & 31); | ||
210 | |||
211 | p += bit >> 5; | ||
212 | |||
213 | __asm__ __volatile__( | ||
214 | "1: l32i %1, %3, 0\n" | ||
215 | " wsr %1, scompare1\n" | ||
216 | " xor %0, %1, %2\n" | ||
217 | " s32c1i %0, %3, 0\n" | ||
218 | " bne %0, %1, 1b\n" | ||
219 | : "=&a" (tmp), "=&a" (value) | ||
220 | : "a" (mask), "a" (p) | ||
221 | : "memory"); | ||
222 | |||
223 | return tmp & mask; | ||
224 | } | ||
225 | |||
226 | #else | ||
227 | |||
228 | #include <asm-generic/bitops/atomic.h> | ||
229 | |||
230 | #endif /* XCHAL_HAVE_S32C1I */ | ||
231 | |||
107 | #include <asm-generic/bitops/find.h> | 232 | #include <asm-generic/bitops/find.h> |
108 | #include <asm-generic/bitops/le.h> | 233 | #include <asm-generic/bitops/le.h> |
109 | 234 | ||
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h index 9983f2c1b7ee..0c25799facab 100644 --- a/arch/xtensa/include/asm/bootparam.h +++ b/arch/xtensa/include/asm/bootparam.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */ | 22 | #define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */ |
23 | #define BP_TAG_SERIAL_BAUSRATE 0x1004 /* baud rate of current console. */ | 23 | #define BP_TAG_SERIAL_BAUSRATE 0x1004 /* baud rate of current console. */ |
24 | #define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */ | 24 | #define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */ |
25 | #define BP_TAG_FDT 0x1006 /* flat device tree addr */ | ||
25 | 26 | ||
26 | #define BP_TAG_FIRST 0x7B0B /* first tag with a version number */ | 27 | #define BP_TAG_FIRST 0x7B0B /* first tag with a version number */ |
27 | #define BP_TAG_LAST 0x7E0B /* last tag */ | 28 | #define BP_TAG_LAST 0x7E0B /* last tag */ |
@@ -31,15 +32,15 @@ | |||
31 | /* All records are aligned to 4 bytes */ | 32 | /* All records are aligned to 4 bytes */ |
32 | 33 | ||
33 | typedef struct bp_tag { | 34 | typedef struct bp_tag { |
34 | unsigned short id; /* tag id */ | 35 | unsigned short id; /* tag id */ |
35 | unsigned short size; /* size of this record excluding the structure*/ | 36 | unsigned short size; /* size of this record excluding the structure*/ |
36 | unsigned long data[0]; /* data */ | 37 | unsigned long data[0]; /* data */ |
37 | } bp_tag_t; | 38 | } bp_tag_t; |
38 | 39 | ||
39 | typedef struct meminfo { | 40 | typedef struct meminfo { |
40 | unsigned long type; | 41 | unsigned long type; |
41 | unsigned long start; | 42 | unsigned long start; |
42 | unsigned long end; | 43 | unsigned long end; |
43 | } meminfo_t; | 44 | } meminfo_t; |
44 | 45 | ||
45 | #define SYSMEM_BANKS_MAX 5 | 46 | #define SYSMEM_BANKS_MAX 5 |
@@ -48,14 +49,11 @@ typedef struct meminfo { | |||
48 | #define MEMORY_TYPE_NONE 0x2000 | 49 | #define MEMORY_TYPE_NONE 0x2000 |
49 | 50 | ||
50 | typedef struct sysmem_info { | 51 | typedef struct sysmem_info { |
51 | int nr_banks; | 52 | int nr_banks; |
52 | meminfo_t bank[SYSMEM_BANKS_MAX]; | 53 | meminfo_t bank[SYSMEM_BANKS_MAX]; |
53 | } sysmem_info_t; | 54 | } sysmem_info_t; |
54 | 55 | ||
55 | extern sysmem_info_t sysmem; | 56 | extern sysmem_info_t sysmem; |
56 | 57 | ||
57 | #endif | 58 | #endif |
58 | #endif | 59 | #endif |
59 | |||
60 | |||
61 | |||
diff --git a/arch/xtensa/include/asm/cacheasm.h b/arch/xtensa/include/asm/cacheasm.h index 2c20a58f94cd..60e18773ecb8 100644 --- a/arch/xtensa/include/asm/cacheasm.h +++ b/arch/xtensa/include/asm/cacheasm.h | |||
@@ -174,4 +174,3 @@ | |||
174 | __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH | 174 | __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH |
175 | 175 | ||
176 | .endm | 176 | .endm |
177 | |||
diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h index 569fec4f9a20..127cd48883c4 100644 --- a/arch/xtensa/include/asm/cacheflush.h +++ b/arch/xtensa/include/asm/cacheflush.h | |||
@@ -104,7 +104,8 @@ static inline void __invalidate_icache_page_alias(unsigned long virt, | |||
104 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | 104 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 |
105 | extern void flush_dcache_page(struct page*); | 105 | extern void flush_dcache_page(struct page*); |
106 | extern void flush_cache_range(struct vm_area_struct*, ulong, ulong); | 106 | extern void flush_cache_range(struct vm_area_struct*, ulong, ulong); |
107 | extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long); | 107 | extern void flush_cache_page(struct vm_area_struct*, |
108 | unsigned long, unsigned long); | ||
108 | 109 | ||
109 | #else | 110 | #else |
110 | 111 | ||
diff --git a/arch/xtensa/include/asm/checksum.h b/arch/xtensa/include/asm/checksum.h index e4d831a30772..aed7ad68ca46 100644 --- a/arch/xtensa/include/asm/checksum.h +++ b/arch/xtensa/include/asm/checksum.h | |||
@@ -36,8 +36,9 @@ asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum); | |||
36 | * better 64-bit) boundary | 36 | * better 64-bit) boundary |
37 | */ | 37 | */ |
38 | 38 | ||
39 | asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, int len, __wsum sum, | 39 | asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, |
40 | int *src_err_ptr, int *dst_err_ptr); | 40 | int len, __wsum sum, |
41 | int *src_err_ptr, int *dst_err_ptr); | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Note: when you get a NULL pointer exception here this means someone | 44 | * Note: when you get a NULL pointer exception here this means someone |
@@ -54,7 +55,7 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, | |||
54 | 55 | ||
55 | static inline | 56 | static inline |
56 | __wsum csum_partial_copy_from_user(const void __user *src, void *dst, | 57 | __wsum csum_partial_copy_from_user(const void __user *src, void *dst, |
57 | int len, __wsum sum, int *err_ptr) | 58 | int len, __wsum sum, int *err_ptr) |
58 | { | 59 | { |
59 | return csum_partial_copy_generic((__force const void *)src, dst, | 60 | return csum_partial_copy_generic((__force const void *)src, dst, |
60 | len, sum, err_ptr, NULL); | 61 | len, sum, err_ptr, NULL); |
@@ -112,7 +113,8 @@ static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl) | |||
112 | /* Since the input registers which are loaded with iph and ihl | 113 | /* Since the input registers which are loaded with iph and ihl |
113 | are modified, we must also specify them as outputs, or gcc | 114 | are modified, we must also specify them as outputs, or gcc |
114 | will assume they contain their original values. */ | 115 | will assume they contain their original values. */ |
115 | : "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp), "=&r" (endaddr) | 116 | : "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp), |
117 | "=&r" (endaddr) | ||
116 | : "1" (iph), "2" (ihl) | 118 | : "1" (iph), "2" (ihl) |
117 | : "memory"); | 119 | : "memory"); |
118 | 120 | ||
@@ -168,7 +170,7 @@ static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, | |||
168 | 170 | ||
169 | static __inline__ __sum16 ip_compute_csum(const void *buff, int len) | 171 | static __inline__ __sum16 ip_compute_csum(const void *buff, int len) |
170 | { | 172 | { |
171 | return csum_fold (csum_partial(buff, len, 0)); | 173 | return csum_fold (csum_partial(buff, len, 0)); |
172 | } | 174 | } |
173 | 175 | ||
174 | #define _HAVE_ARCH_IPV6_CSUM | 176 | #define _HAVE_ARCH_IPV6_CSUM |
@@ -238,11 +240,12 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, | |||
238 | * Copy and checksum to user | 240 | * Copy and checksum to user |
239 | */ | 241 | */ |
240 | #define HAVE_CSUM_COPY_USER | 242 | #define HAVE_CSUM_COPY_USER |
241 | static __inline__ __wsum csum_and_copy_to_user(const void *src, void __user *dst, | 243 | static __inline__ __wsum csum_and_copy_to_user(const void *src, |
242 | int len, __wsum sum, int *err_ptr) | 244 | void __user *dst, int len, |
245 | __wsum sum, int *err_ptr) | ||
243 | { | 246 | { |
244 | if (access_ok(VERIFY_WRITE, dst, len)) | 247 | if (access_ok(VERIFY_WRITE, dst, len)) |
245 | return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr); | 248 | return csum_partial_copy_generic(src,dst,len,sum,NULL,err_ptr); |
246 | 249 | ||
247 | if (len) | 250 | if (len) |
248 | *err_ptr = -EFAULT; | 251 | *err_ptr = -EFAULT; |
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index 64dad04a9d27..d9ab131bc1aa 100644 --- a/arch/xtensa/include/asm/cmpxchg.h +++ b/arch/xtensa/include/asm/cmpxchg.h | |||
@@ -22,17 +22,30 @@ | |||
22 | static inline unsigned long | 22 | static inline unsigned long |
23 | __cmpxchg_u32(volatile int *p, int old, int new) | 23 | __cmpxchg_u32(volatile int *p, int old, int new) |
24 | { | 24 | { |
25 | __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 25 | #if XCHAL_HAVE_S32C1I |
26 | "l32i %0, %1, 0 \n\t" | 26 | __asm__ __volatile__( |
27 | "bne %0, %2, 1f \n\t" | 27 | " wsr %2, scompare1\n" |
28 | "s32i %3, %1, 0 \n\t" | 28 | " s32c1i %0, %1, 0\n" |
29 | "1: \n\t" | 29 | : "+a" (new) |
30 | "wsr a15, ps \n\t" | 30 | : "a" (p), "a" (old) |
31 | "rsync \n\t" | 31 | : "memory" |
32 | : "=&a" (old) | 32 | ); |
33 | : "a" (p), "a" (old), "r" (new) | 33 | |
34 | : "a15", "memory"); | 34 | return new; |
35 | return old; | 35 | #else |
36 | __asm__ __volatile__( | ||
37 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
38 | " l32i %0, %1, 0\n" | ||
39 | " bne %0, %2, 1f\n" | ||
40 | " s32i %3, %1, 0\n" | ||
41 | "1:\n" | ||
42 | " wsr a15, ps\n" | ||
43 | " rsync\n" | ||
44 | : "=&a" (old) | ||
45 | : "a" (p), "a" (old), "r" (new) | ||
46 | : "a15", "memory"); | ||
47 | return old; | ||
48 | #endif | ||
36 | } | 49 | } |
37 | /* This function doesn't exist, so you'll get a linker error | 50 | /* This function doesn't exist, so you'll get a linker error |
38 | * if something tries to do an invalid cmpxchg(). */ | 51 | * if something tries to do an invalid cmpxchg(). */ |
@@ -93,19 +106,36 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, | |||
93 | 106 | ||
94 | static inline unsigned long xchg_u32(volatile int * m, unsigned long val) | 107 | static inline unsigned long xchg_u32(volatile int * m, unsigned long val) |
95 | { | 108 | { |
96 | unsigned long tmp; | 109 | #if XCHAL_HAVE_S32C1I |
97 | __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t" | 110 | unsigned long tmp, result; |
98 | "l32i %0, %1, 0 \n\t" | 111 | __asm__ __volatile__( |
99 | "s32i %2, %1, 0 \n\t" | 112 | "1: l32i %1, %2, 0\n" |
100 | "wsr a15, ps \n\t" | 113 | " mov %0, %3\n" |
101 | "rsync \n\t" | 114 | " wsr %1, scompare1\n" |
102 | : "=&a" (tmp) | 115 | " s32c1i %0, %2, 0\n" |
103 | : "a" (m), "a" (val) | 116 | " bne %0, %1, 1b\n" |
104 | : "a15", "memory"); | 117 | : "=&a" (result), "=&a" (tmp) |
105 | return tmp; | 118 | : "a" (m), "a" (val) |
119 | : "memory" | ||
120 | ); | ||
121 | return result; | ||
122 | #else | ||
123 | unsigned long tmp; | ||
124 | __asm__ __volatile__( | ||
125 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
126 | " l32i %0, %1, 0\n" | ||
127 | " s32i %2, %1, 0\n" | ||
128 | " wsr a15, ps\n" | ||
129 | " rsync\n" | ||
130 | : "=&a" (tmp) | ||
131 | : "a" (m), "a" (val) | ||
132 | : "a15", "memory"); | ||
133 | return tmp; | ||
134 | #endif | ||
106 | } | 135 | } |
107 | 136 | ||
108 | #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | 137 | #define xchg(ptr,x) \ |
138 | ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | ||
109 | 139 | ||
110 | /* | 140 | /* |
111 | * This only works if the compiler isn't horribly bad at optimizing. | 141 | * This only works if the compiler isn't horribly bad at optimizing. |
diff --git a/arch/xtensa/include/asm/current.h b/arch/xtensa/include/asm/current.h index 8d1eb5d78649..47e46dcf5d49 100644 --- a/arch/xtensa/include/asm/current.h +++ b/arch/xtensa/include/asm/current.h | |||
@@ -30,7 +30,7 @@ static inline struct task_struct *get_current(void) | |||
30 | 30 | ||
31 | #define GET_CURRENT(reg,sp) \ | 31 | #define GET_CURRENT(reg,sp) \ |
32 | GET_THREAD_INFO(reg,sp); \ | 32 | GET_THREAD_INFO(reg,sp); \ |
33 | l32i reg, reg, TI_TASK \ | 33 | l32i reg, reg, TI_TASK \ |
34 | 34 | ||
35 | #endif | 35 | #endif |
36 | 36 | ||
diff --git a/arch/xtensa/include/asm/delay.h b/arch/xtensa/include/asm/delay.h index 58c0a4fd4003..61fc5faeb46c 100644 --- a/arch/xtensa/include/asm/delay.h +++ b/arch/xtensa/include/asm/delay.h | |||
@@ -19,9 +19,9 @@ extern unsigned long loops_per_jiffy; | |||
19 | 19 | ||
20 | static inline void __delay(unsigned long loops) | 20 | static inline void __delay(unsigned long loops) |
21 | { | 21 | { |
22 | /* 2 cycles per loop. */ | 22 | /* 2 cycles per loop. */ |
23 | __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b" | 23 | __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b" |
24 | : "=r" (loops) : "0" (loops)); | 24 | : "=r" (loops) : "0" (loops)); |
25 | } | 25 | } |
26 | 26 | ||
27 | static __inline__ u32 xtensa_get_ccount(void) | 27 | static __inline__ u32 xtensa_get_ccount(void) |
@@ -46,4 +46,3 @@ static __inline__ void udelay (unsigned long usecs) | |||
46 | } | 46 | } |
47 | 47 | ||
48 | #endif | 48 | #endif |
49 | |||
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h index 492c95790ad5..4acb5feba1fb 100644 --- a/arch/xtensa/include/asm/dma-mapping.h +++ b/arch/xtensa/include/asm/dma-mapping.h | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/scatterlist.h> | 17 | #include <linux/scatterlist.h> |
18 | 18 | ||
19 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) | ||
20 | |||
19 | /* | 21 | /* |
20 | * DMA-consistent mapping functions. | 22 | * DMA-consistent mapping functions. |
21 | */ | 23 | */ |
@@ -98,8 +100,8 @@ dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, | |||
98 | } | 100 | } |
99 | 101 | ||
100 | static inline void | 102 | static inline void |
101 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, | 103 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, |
102 | enum dma_data_direction direction) | 104 | size_t size, enum dma_data_direction direction) |
103 | { | 105 | { |
104 | consistent_sync((void *)bus_to_virt(dma_handle), size, direction); | 106 | consistent_sync((void *)bus_to_virt(dma_handle), size, direction); |
105 | } | 107 | } |
diff --git a/arch/xtensa/include/asm/elf.h b/arch/xtensa/include/asm/elf.h index 5293312bc6a4..264d5fa450d8 100644 --- a/arch/xtensa/include/asm/elf.h +++ b/arch/xtensa/include/asm/elf.h | |||
@@ -168,11 +168,11 @@ extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *); | |||
168 | */ | 168 | */ |
169 | 169 | ||
170 | #define ELF_PLAT_INIT(_r, load_addr) \ | 170 | #define ELF_PLAT_INIT(_r, load_addr) \ |
171 | do { _r->areg[0]=0; /*_r->areg[1]=0;*/ _r->areg[2]=0; _r->areg[3]=0; \ | 171 | do { _r->areg[0]=0; /*_r->areg[1]=0;*/ _r->areg[2]=0; _r->areg[3]=0; \ |
172 | _r->areg[4]=0; _r->areg[5]=0; _r->areg[6]=0; _r->areg[7]=0; \ | 172 | _r->areg[4]=0; _r->areg[5]=0; _r->areg[6]=0; _r->areg[7]=0; \ |
173 | _r->areg[8]=0; _r->areg[9]=0; _r->areg[10]=0; _r->areg[11]=0; \ | 173 | _r->areg[8]=0; _r->areg[9]=0; _r->areg[10]=0; _r->areg[11]=0; \ |
174 | _r->areg[12]=0; _r->areg[13]=0; _r->areg[14]=0; _r->areg[15]=0; \ | 174 | _r->areg[12]=0; _r->areg[13]=0; _r->areg[14]=0; _r->areg[15]=0; \ |
175 | } while (0) | 175 | } while (0) |
176 | 176 | ||
177 | typedef struct { | 177 | typedef struct { |
178 | xtregs_opt_t opt; | 178 | xtregs_opt_t opt; |
diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h index 0a046ca5a687..80be15124697 100644 --- a/arch/xtensa/include/asm/highmem.h +++ b/arch/xtensa/include/asm/highmem.h | |||
@@ -14,4 +14,3 @@ | |||
14 | extern void flush_cache_kmaps(void); | 14 | extern void flush_cache_kmaps(void); |
15 | 15 | ||
16 | #endif | 16 | #endif |
17 | |||
diff --git a/arch/xtensa/include/asm/initialize_mmu.h b/arch/xtensa/include/asm/initialize_mmu.h new file mode 100644 index 000000000000..e1f8ba4061ed --- /dev/null +++ b/arch/xtensa/include/asm/initialize_mmu.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * arch/xtensa/include/asm/initialize_mmu.h | ||
3 | * | ||
4 | * Initializes MMU: | ||
5 | * | ||
6 | * For the new V3 MMU we remap the TLB from virtual == physical | ||
7 | * to the standard Linux mapping used in earlier MMU's. | ||
8 | * | ||
9 | * The the MMU we also support a new configuration register that | ||
10 | * specifies how the S32C1I instruction operates with the cache | ||
11 | * controller. | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General | ||
14 | * Public License. See the file "COPYING" in the main directory of | ||
15 | * this archive for more details. | ||
16 | * | ||
17 | * Copyright (C) 2008 - 2012 Tensilica, Inc. | ||
18 | * | ||
19 | * Marc Gauthier <marc@tensilica.com> | ||
20 | * Pete Delaney <piet@tensilica.com> | ||
21 | */ | ||
22 | |||
23 | #ifndef _XTENSA_INITIALIZE_MMU_H | ||
24 | #define _XTENSA_INITIALIZE_MMU_H | ||
25 | |||
26 | #ifdef __ASSEMBLY__ | ||
27 | |||
28 | #define XTENSA_HWVERSION_RC_2009_0 230000 | ||
29 | |||
30 | .macro initialize_mmu | ||
31 | |||
32 | #if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) | ||
33 | /* | ||
34 | * We Have Atomic Operation Control (ATOMCTL) Register; Initialize it. | ||
35 | * For details see Documentation/xtensa/atomctl.txt | ||
36 | */ | ||
37 | #if XCHAL_DCACHE_IS_COHERENT | ||
38 | movi a3, 0x25 /* For SMP/MX -- internal for writeback, | ||
39 | * RCW otherwise | ||
40 | */ | ||
41 | #else | ||
42 | movi a3, 0x29 /* non-MX -- Most cores use Std Memory | ||
43 | * Controlers which usually can't use RCW | ||
44 | */ | ||
45 | #endif | ||
46 | wsr a3, atomctl | ||
47 | #endif /* XCHAL_HAVE_S32C1I && | ||
48 | * (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) | ||
49 | */ | ||
50 | |||
51 | .endm | ||
52 | |||
53 | #endif /*__ASSEMBLY__*/ | ||
54 | |||
55 | #endif /* _XTENSA_INITIALIZE_MMU_H */ | ||
diff --git a/arch/xtensa/include/asm/mmu_context.h b/arch/xtensa/include/asm/mmu_context.h index feb10af96519..d43525a286bb 100644 --- a/arch/xtensa/include/asm/mmu_context.h +++ b/arch/xtensa/include/asm/mmu_context.h | |||
@@ -107,7 +107,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next) | |||
107 | 107 | ||
108 | 108 | ||
109 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 109 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
110 | struct task_struct *tsk) | 110 | struct task_struct *tsk) |
111 | { | 111 | { |
112 | unsigned long asid = asid_cache; | 112 | unsigned long asid = asid_cache; |
113 | 113 | ||
diff --git a/arch/xtensa/include/asm/nommu_context.h b/arch/xtensa/include/asm/nommu_context.h index 599e7a2e729d..3407cf7989b7 100644 --- a/arch/xtensa/include/asm/nommu_context.h +++ b/arch/xtensa/include/asm/nommu_context.h | |||
@@ -2,7 +2,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | |||
2 | { | 2 | { |
3 | } | 3 | } |
4 | 4 | ||
5 | static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 5 | static inline int init_new_context(struct task_struct *tsk,struct mm_struct *mm) |
6 | { | 6 | { |
7 | return 0; | 7 | return 0; |
8 | } | 8 | } |
diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 7a5591a71f85..47f582333f6b 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h | |||
@@ -29,19 +29,19 @@ | |||
29 | * PAGE_SHIFT determines the page size | 29 | * PAGE_SHIFT determines the page size |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #define PAGE_SHIFT 12 | 32 | #define PAGE_SHIFT 12 |
33 | #define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT) | 33 | #define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT) |
34 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 34 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
35 | 35 | ||
36 | #ifdef CONFIG_MMU | 36 | #ifdef CONFIG_MMU |
37 | #define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR | 37 | #define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR |
38 | #define MAX_MEM_PFN XCHAL_KSEG_SIZE | 38 | #define MAX_MEM_PFN XCHAL_KSEG_SIZE |
39 | #else | 39 | #else |
40 | #define PAGE_OFFSET 0 | 40 | #define PAGE_OFFSET 0 |
41 | #define MAX_MEM_PFN (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE) | 41 | #define MAX_MEM_PFN (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE) |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #define PGTABLE_START 0x80000000 | 44 | #define PGTABLE_START 0x80000000 |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Cache aliasing: | 47 | * Cache aliasing: |
@@ -161,7 +161,9 @@ extern void copy_user_page(void*, void*, unsigned long, struct page*); | |||
161 | 161 | ||
162 | #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) | 162 | #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) |
163 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) | 163 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) |
164 | #define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr) | 164 | #define pfn_valid(pfn) \ |
165 | ((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr) | ||
166 | |||
165 | #ifdef CONFIG_DISCONTIGMEM | 167 | #ifdef CONFIG_DISCONTIGMEM |
166 | # error CONFIG_DISCONTIGMEM not supported | 168 | # error CONFIG_DISCONTIGMEM not supported |
167 | #endif | 169 | #endif |
diff --git a/arch/xtensa/include/asm/pci-bridge.h b/arch/xtensa/include/asm/pci-bridge.h index 00fcbd7c534a..0b68c76ec1e6 100644 --- a/arch/xtensa/include/asm/pci-bridge.h +++ b/arch/xtensa/include/asm/pci-bridge.h | |||
@@ -35,7 +35,7 @@ struct pci_space { | |||
35 | struct pci_controller { | 35 | struct pci_controller { |
36 | int index; /* used for pci_controller_num */ | 36 | int index; /* used for pci_controller_num */ |
37 | struct pci_controller *next; | 37 | struct pci_controller *next; |
38 | struct pci_bus *bus; | 38 | struct pci_bus *bus; |
39 | void *arch_data; | 39 | void *arch_data; |
40 | 40 | ||
41 | int first_busno; | 41 | int first_busno; |
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h index 05244f07dd31..614be031a79a 100644 --- a/arch/xtensa/include/asm/pci.h +++ b/arch/xtensa/include/asm/pci.h | |||
@@ -53,7 +53,7 @@ struct pci_dev; | |||
53 | 53 | ||
54 | /* Map a range of PCI memory or I/O space for a device into user space */ | 54 | /* Map a range of PCI memory or I/O space for a device into user space */ |
55 | int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, | 55 | int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, |
56 | enum pci_mmap_state mmap_state, int write_combine); | 56 | enum pci_mmap_state mmap_state, int write_combine); |
57 | 57 | ||
58 | /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ | 58 | /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ |
59 | #define HAVE_PCI_MMAP 1 | 59 | #define HAVE_PCI_MMAP 1 |
diff --git a/arch/xtensa/include/asm/pgalloc.h b/arch/xtensa/include/asm/pgalloc.h index 40cf9bceda2c..cf914c8c249a 100644 --- a/arch/xtensa/include/asm/pgalloc.h +++ b/arch/xtensa/include/asm/pgalloc.h | |||
@@ -42,7 +42,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | |||
42 | 42 | ||
43 | extern struct kmem_cache *pgtable_cache; | 43 | extern struct kmem_cache *pgtable_cache; |
44 | 44 | ||
45 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 45 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
46 | unsigned long address) | 46 | unsigned long address) |
47 | { | 47 | { |
48 | return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT); | 48 | return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT); |
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index b03c043ce75b..c90ea5bfa1b4 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h | |||
@@ -284,7 +284,7 @@ struct vm_area_struct; | |||
284 | 284 | ||
285 | static inline int | 285 | static inline int |
286 | ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, | 286 | ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, |
287 | pte_t *ptep) | 287 | pte_t *ptep) |
288 | { | 288 | { |
289 | pte_t pte = *ptep; | 289 | pte_t pte = *ptep; |
290 | if (!pte_young(pte)) | 290 | if (!pte_young(pte)) |
@@ -304,8 +304,8 @@ ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | |||
304 | static inline void | 304 | static inline void |
305 | ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 305 | ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
306 | { | 306 | { |
307 | pte_t pte = *ptep; | 307 | pte_t pte = *ptep; |
308 | update_pte(ptep, pte_wrprotect(pte)); | 308 | update_pte(ptep, pte_wrprotect(pte)); |
309 | } | 309 | } |
310 | 310 | ||
311 | /* to find an entry in a kernel page-table-directory */ | 311 | /* to find an entry in a kernel page-table-directory */ |
@@ -399,7 +399,7 @@ extern void update_mmu_cache(struct vm_area_struct * vma, | |||
399 | */ | 399 | */ |
400 | 400 | ||
401 | #define io_remap_pfn_range(vma,from,pfn,size,prot) \ | 401 | #define io_remap_pfn_range(vma,from,pfn,size,prot) \ |
402 | remap_pfn_range(vma, from, pfn, size, prot) | 402 | remap_pfn_range(vma, from, pfn, size, prot) |
403 | 403 | ||
404 | typedef pte_t *pte_addr_t; | 404 | typedef pte_t *pte_addr_t; |
405 | 405 | ||
diff --git a/arch/xtensa/include/asm/platform.h b/arch/xtensa/include/asm/platform.h index 7d936e58e9be..ec098b68fb9a 100644 --- a/arch/xtensa/include/asm/platform.h +++ b/arch/xtensa/include/asm/platform.h | |||
@@ -75,4 +75,3 @@ extern int platform_pcibios_fixup (void); | |||
75 | extern void platform_calibrate_ccount (void); | 75 | extern void platform_calibrate_ccount (void); |
76 | 76 | ||
77 | #endif /* _XTENSA_PLATFORM_H */ | 77 | #endif /* _XTENSA_PLATFORM_H */ |
78 | |||
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 2d630e7399ca..e5fb6b0abdf4 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h | |||
@@ -89,7 +89,7 @@ | |||
89 | #define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) | 89 | #define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) |
90 | 90 | ||
91 | typedef struct { | 91 | typedef struct { |
92 | unsigned long seg; | 92 | unsigned long seg; |
93 | } mm_segment_t; | 93 | } mm_segment_t; |
94 | 94 | ||
95 | struct thread_struct { | 95 | struct thread_struct { |
@@ -145,10 +145,10 @@ struct thread_struct { | |||
145 | * set_thread_state in signal.c depends on it. | 145 | * set_thread_state in signal.c depends on it. |
146 | */ | 146 | */ |
147 | #define USER_PS_VALUE ((1 << PS_WOE_BIT) | \ | 147 | #define USER_PS_VALUE ((1 << PS_WOE_BIT) | \ |
148 | (1 << PS_CALLINC_SHIFT) | \ | 148 | (1 << PS_CALLINC_SHIFT) | \ |
149 | (USER_RING << PS_RING_SHIFT) | \ | 149 | (USER_RING << PS_RING_SHIFT) | \ |
150 | (1 << PS_UM_BIT) | \ | 150 | (1 << PS_UM_BIT) | \ |
151 | (1 << PS_EXCM_BIT)) | 151 | (1 << PS_EXCM_BIT)) |
152 | 152 | ||
153 | /* Clearing a0 terminates the backtrace. */ | 153 | /* Clearing a0 terminates the backtrace. */ |
154 | #define start_thread(regs, new_pc, new_sp) \ | 154 | #define start_thread(regs, new_pc, new_sp) \ |
diff --git a/arch/xtensa/include/asm/prom.h b/arch/xtensa/include/asm/prom.h new file mode 100644 index 000000000000..f3d7cd2c0de7 --- /dev/null +++ b/arch/xtensa/include/asm/prom.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _XTENSA_ASM_PROM_H | ||
2 | #define _XTENSA_ASM_PROM_H | ||
3 | |||
4 | #define HAVE_ARCH_DEVTREE_FIXUPS | ||
5 | |||
6 | #endif /* _XTENSA_ASM_PROM_H */ | ||
diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h index da21c17f23aa..58bf6fd3f913 100644 --- a/arch/xtensa/include/asm/ptrace.h +++ b/arch/xtensa/include/asm/ptrace.h | |||
@@ -37,7 +37,7 @@ struct pt_regs { | |||
37 | unsigned long windowstart; /* 52 */ | 37 | unsigned long windowstart; /* 52 */ |
38 | unsigned long syscall; /* 56 */ | 38 | unsigned long syscall; /* 56 */ |
39 | unsigned long icountlevel; /* 60 */ | 39 | unsigned long icountlevel; /* 60 */ |
40 | int reserved[1]; /* 64 */ | 40 | unsigned long scompare1; /* 64 */ |
41 | 41 | ||
42 | /* Additional configurable registers that are used by the compiler. */ | 42 | /* Additional configurable registers that are used by the compiler. */ |
43 | xtregs_opt_t xtregs_opt; | 43 | xtregs_opt_t xtregs_opt; |
@@ -55,7 +55,7 @@ struct pt_regs { | |||
55 | 55 | ||
56 | # define arch_has_single_step() (1) | 56 | # define arch_has_single_step() (1) |
57 | # define task_pt_regs(tsk) ((struct pt_regs*) \ | 57 | # define task_pt_regs(tsk) ((struct pt_regs*) \ |
58 | (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1) | 58 | (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1) |
59 | # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) | 59 | # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) |
60 | # define instruction_pointer(regs) ((regs)->pc) | 60 | # define instruction_pointer(regs) ((regs)->pc) |
61 | 61 | ||
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h index 8a8aa61ccc8d..76096a4e5b8d 100644 --- a/arch/xtensa/include/asm/regs.h +++ b/arch/xtensa/include/asm/regs.h | |||
@@ -52,6 +52,10 @@ | |||
52 | #define EXCCAUSE_SPECULATION 7 | 52 | #define EXCCAUSE_SPECULATION 7 |
53 | #define EXCCAUSE_PRIVILEGED 8 | 53 | #define EXCCAUSE_PRIVILEGED 8 |
54 | #define EXCCAUSE_UNALIGNED 9 | 54 | #define EXCCAUSE_UNALIGNED 9 |
55 | #define EXCCAUSE_INSTR_DATA_ERROR 12 | ||
56 | #define EXCCAUSE_LOAD_STORE_DATA_ERROR 13 | ||
57 | #define EXCCAUSE_INSTR_ADDR_ERROR 14 | ||
58 | #define EXCCAUSE_LOAD_STORE_ADDR_ERROR 15 | ||
55 | #define EXCCAUSE_ITLB_MISS 16 | 59 | #define EXCCAUSE_ITLB_MISS 16 |
56 | #define EXCCAUSE_ITLB_MULTIHIT 17 | 60 | #define EXCCAUSE_ITLB_MULTIHIT 17 |
57 | #define EXCCAUSE_ITLB_PRIVILEGE 18 | 61 | #define EXCCAUSE_ITLB_PRIVILEGE 18 |
@@ -105,4 +109,3 @@ | |||
105 | #define DEBUGCAUSE_ICOUNT_BIT 0 /* ICOUNT would incr. to zero */ | 109 | #define DEBUGCAUSE_ICOUNT_BIT 0 /* ICOUNT would incr. to zero */ |
106 | 110 | ||
107 | #endif /* _XTENSA_SPECREG_H */ | 111 | #endif /* _XTENSA_SPECREG_H */ |
108 | |||
diff --git a/arch/xtensa/include/asm/spinlock.h b/arch/xtensa/include/asm/spinlock.h index 8ff23649581b..03975906b36f 100644 --- a/arch/xtensa/include/asm/spinlock.h +++ b/arch/xtensa/include/asm/spinlock.h | |||
@@ -11,6 +11,192 @@ | |||
11 | #ifndef _XTENSA_SPINLOCK_H | 11 | #ifndef _XTENSA_SPINLOCK_H |
12 | #define _XTENSA_SPINLOCK_H | 12 | #define _XTENSA_SPINLOCK_H |
13 | 13 | ||
14 | #include <linux/spinlock.h> | 14 | /* |
15 | * spinlock | ||
16 | * | ||
17 | * There is at most one owner of a spinlock. There are not different | ||
18 | * types of spinlock owners like there are for rwlocks (see below). | ||
19 | * | ||
20 | * When trying to obtain a spinlock, the function "spins" forever, or busy- | ||
21 | * waits, until the lock is obtained. When spinning, presumably some other | ||
22 | * owner will soon give up the spinlock making it available to others. Use | ||
23 | * the trylock functions to avoid spinning forever. | ||
24 | * | ||
25 | * possible values: | ||
26 | * | ||
27 | * 0 nobody owns the spinlock | ||
28 | * 1 somebody owns the spinlock | ||
29 | */ | ||
30 | |||
31 | #define __raw_spin_is_locked(x) ((x)->slock != 0) | ||
32 | #define __raw_spin_unlock_wait(lock) \ | ||
33 | do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) | ||
34 | |||
35 | #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) | ||
36 | |||
37 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | ||
38 | { | ||
39 | unsigned long tmp; | ||
40 | |||
41 | __asm__ __volatile__( | ||
42 | " movi %0, 0\n" | ||
43 | " wsr %0, scompare1\n" | ||
44 | "1: movi %0, 1\n" | ||
45 | " s32c1i %0, %1, 0\n" | ||
46 | " bnez %0, 1b\n" | ||
47 | : "=&a" (tmp) | ||
48 | : "a" (&lock->slock) | ||
49 | : "memory"); | ||
50 | } | ||
51 | |||
52 | /* Returns 1 if the lock is obtained, 0 otherwise. */ | ||
53 | |||
54 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | ||
55 | { | ||
56 | unsigned long tmp; | ||
57 | |||
58 | __asm__ __volatile__( | ||
59 | " movi %0, 0\n" | ||
60 | " wsr %0, scompare1\n" | ||
61 | " movi %0, 1\n" | ||
62 | " s32c1i %0, %1, 0\n" | ||
63 | : "=&a" (tmp) | ||
64 | : "a" (&lock->slock) | ||
65 | : "memory"); | ||
66 | |||
67 | return tmp == 0 ? 1 : 0; | ||
68 | } | ||
69 | |||
70 | static inline void __raw_spin_unlock(raw_spinlock_t *lock) | ||
71 | { | ||
72 | unsigned long tmp; | ||
73 | |||
74 | __asm__ __volatile__( | ||
75 | " movi %0, 0\n" | ||
76 | " s32ri %0, %1, 0\n" | ||
77 | : "=&a" (tmp) | ||
78 | : "a" (&lock->slock) | ||
79 | : "memory"); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * rwlock | ||
84 | * | ||
85 | * Read-write locks are really a more flexible spinlock. They allow | ||
86 | * multiple readers but only one writer. Write ownership is exclusive | ||
87 | * (i.e., all other readers and writers are blocked from ownership while | ||
88 | * there is a write owner). These rwlocks are unfair to writers. Writers | ||
89 | * can be starved for an indefinite time by readers. | ||
90 | * | ||
91 | * possible values: | ||
92 | * | ||
93 | * 0 nobody owns the rwlock | ||
94 | * >0 one or more readers own the rwlock | ||
95 | * (the positive value is the actual number of readers) | ||
96 | * 0x80000000 one writer owns the rwlock, no other writers, no readers | ||
97 | */ | ||
98 | |||
99 | #define __raw_write_can_lock(x) ((x)->lock == 0) | ||
100 | |||
101 | static inline void __raw_write_lock(raw_rwlock_t *rw) | ||
102 | { | ||
103 | unsigned long tmp; | ||
104 | |||
105 | __asm__ __volatile__( | ||
106 | " movi %0, 0\n" | ||
107 | " wsr %0, scompare1\n" | ||
108 | "1: movi %0, 1\n" | ||
109 | " slli %0, %0, 31\n" | ||
110 | " s32c1i %0, %1, 0\n" | ||
111 | " bnez %0, 1b\n" | ||
112 | : "=&a" (tmp) | ||
113 | : "a" (&rw->lock) | ||
114 | : "memory"); | ||
115 | } | ||
116 | |||
117 | /* Returns 1 if the lock is obtained, 0 otherwise. */ | ||
118 | |||
119 | static inline int __raw_write_trylock(raw_rwlock_t *rw) | ||
120 | { | ||
121 | unsigned long tmp; | ||
122 | |||
123 | __asm__ __volatile__( | ||
124 | " movi %0, 0\n" | ||
125 | " wsr %0, scompare1\n" | ||
126 | " movi %0, 1\n" | ||
127 | " slli %0, %0, 31\n" | ||
128 | " s32c1i %0, %1, 0\n" | ||
129 | : "=&a" (tmp) | ||
130 | : "a" (&rw->lock) | ||
131 | : "memory"); | ||
132 | |||
133 | return tmp == 0 ? 1 : 0; | ||
134 | } | ||
135 | |||
136 | static inline void __raw_write_unlock(raw_rwlock_t *rw) | ||
137 | { | ||
138 | unsigned long tmp; | ||
139 | |||
140 | __asm__ __volatile__( | ||
141 | " movi %0, 0\n" | ||
142 | " s32ri %0, %1, 0\n" | ||
143 | : "=&a" (tmp) | ||
144 | : "a" (&rw->lock) | ||
145 | : "memory"); | ||
146 | } | ||
147 | |||
148 | static inline void __raw_read_lock(raw_rwlock_t *rw) | ||
149 | { | ||
150 | unsigned long tmp; | ||
151 | unsigned long result; | ||
152 | |||
153 | __asm__ __volatile__( | ||
154 | "1: l32i %1, %2, 0\n" | ||
155 | " bltz %1, 1b\n" | ||
156 | " wsr %1, scompare1\n" | ||
157 | " addi %0, %1, 1\n" | ||
158 | " s32c1i %0, %2, 0\n" | ||
159 | " bne %0, %1, 1b\n" | ||
160 | : "=&a" (result), "=&a" (tmp) | ||
161 | : "a" (&rw->lock) | ||
162 | : "memory"); | ||
163 | } | ||
164 | |||
165 | /* Returns 1 if the lock is obtained, 0 otherwise. */ | ||
166 | |||
167 | static inline int __raw_read_trylock(raw_rwlock_t *rw) | ||
168 | { | ||
169 | unsigned long result; | ||
170 | unsigned long tmp; | ||
171 | |||
172 | __asm__ __volatile__( | ||
173 | " l32i %1, %2, 0\n" | ||
174 | " addi %0, %1, 1\n" | ||
175 | " bltz %0, 1f\n" | ||
176 | " wsr %1, scompare1\n" | ||
177 | " s32c1i %0, %2, 0\n" | ||
178 | " sub %0, %0, %1\n" | ||
179 | "1:\n" | ||
180 | : "=&a" (result), "=&a" (tmp) | ||
181 | : "a" (&rw->lock) | ||
182 | : "memory"); | ||
183 | |||
184 | return result == 0; | ||
185 | } | ||
186 | |||
187 | static inline void __raw_read_unlock(raw_rwlock_t *rw) | ||
188 | { | ||
189 | unsigned long tmp1, tmp2; | ||
190 | |||
191 | __asm__ __volatile__( | ||
192 | "1: l32i %1, %2, 0\n" | ||
193 | " addi %0, %1, -1\n" | ||
194 | " wsr %1, scompare1\n" | ||
195 | " s32c1i %0, %2, 0\n" | ||
196 | " bne %0, %1, 1b\n" | ||
197 | : "=&a" (tmp1), "=&a" (tmp2) | ||
198 | : "a" (&rw->lock) | ||
199 | : "memory"); | ||
200 | } | ||
15 | 201 | ||
16 | #endif /* _XTENSA_SPINLOCK_H */ | 202 | #endif /* _XTENSA_SPINLOCK_H */ |
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index b00c928d4cce..8d5e47fad095 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h | |||
@@ -25,9 +25,10 @@ asmlinkage long xtensa_fadvise64_64(int, int, | |||
25 | /* Should probably move to linux/syscalls.h */ | 25 | /* Should probably move to linux/syscalls.h */ |
26 | struct pollfd; | 26 | struct pollfd; |
27 | asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, | 27 | asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, |
28 | fd_set __user *exp, struct timespec __user *tsp, void __user *sig); | 28 | fd_set __user *exp, struct timespec __user *tsp, |
29 | void __user *sig); | ||
29 | asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, | 30 | asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, |
30 | struct timespec __user *tsp, const sigset_t __user *sigmask, | 31 | struct timespec __user *tsp, |
31 | size_t sigsetsize); | 32 | const sigset_t __user *sigmask, |
32 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, | 33 | size_t sigsetsize); |
33 | size_t sigsetsize); | 34 | asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); |
diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h new file mode 100644 index 000000000000..54f70440185e --- /dev/null +++ b/arch/xtensa/include/asm/traps.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * arch/xtensa/include/asm/traps.h | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2012 Tensilica Inc. | ||
9 | */ | ||
10 | #ifndef _XTENSA_TRAPS_H | ||
11 | #define _XTENSA_TRAPS_H | ||
12 | |||
13 | #include <asm/ptrace.h> | ||
14 | |||
15 | /* | ||
16 | * handler must be either of the following: | ||
17 | * void (*)(struct pt_regs *regs); | ||
18 | * void (*)(struct pt_regs *regs, unsigned long exccause); | ||
19 | */ | ||
20 | extern void * __init trap_set_handler(int cause, void *handler); | ||
21 | extern void do_unhandled(struct pt_regs *regs, unsigned long exccause); | ||
22 | |||
23 | #endif /* _XTENSA_TRAPS_H */ | ||
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index 6e4bb3b791ab..fd686dc45d1a 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h | |||
@@ -180,7 +180,8 @@ | |||
180 | #define segment_eq(a,b) ((a).seg == (b).seg) | 180 | #define segment_eq(a,b) ((a).seg == (b).seg) |
181 | 181 | ||
182 | #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) | 182 | #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) |
183 | #define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) | 183 | #define __user_ok(addr,size) \ |
184 | (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) | ||
184 | #define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size))) | 185 | #define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size))) |
185 | #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size)) | 186 | #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size)) |
186 | 187 | ||
@@ -234,10 +235,10 @@ do { \ | |||
234 | int __cb; \ | 235 | int __cb; \ |
235 | retval = 0; \ | 236 | retval = 0; \ |
236 | switch (size) { \ | 237 | switch (size) { \ |
237 | case 1: __put_user_asm(x,ptr,retval,1,"s8i",__cb); break; \ | 238 | case 1: __put_user_asm(x,ptr,retval,1,"s8i",__cb); break; \ |
238 | case 2: __put_user_asm(x,ptr,retval,2,"s16i",__cb); break; \ | 239 | case 2: __put_user_asm(x,ptr,retval,2,"s16i",__cb); break; \ |
239 | case 4: __put_user_asm(x,ptr,retval,4,"s32i",__cb); break; \ | 240 | case 4: __put_user_asm(x,ptr,retval,4,"s32i",__cb); break; \ |
240 | case 8: { \ | 241 | case 8: { \ |
241 | __typeof__(*ptr) __v64 = x; \ | 242 | __typeof__(*ptr) __v64 = x; \ |
242 | retval = __copy_to_user(ptr,&__v64,8); \ | 243 | retval = __copy_to_user(ptr,&__v64,8); \ |
243 | break; \ | 244 | break; \ |
@@ -291,7 +292,7 @@ do { \ | |||
291 | * __check_align_* macros still work. | 292 | * __check_align_* macros still work. |
292 | */ | 293 | */ |
293 | #define __put_user_asm(x, addr, err, align, insn, cb) \ | 294 | #define __put_user_asm(x, addr, err, align, insn, cb) \ |
294 | __asm__ __volatile__( \ | 295 | __asm__ __volatile__( \ |
295 | __check_align_##align \ | 296 | __check_align_##align \ |
296 | "1: "insn" %2, %3, 0 \n" \ | 297 | "1: "insn" %2, %3, 0 \n" \ |
297 | "2: \n" \ | 298 | "2: \n" \ |
@@ -301,8 +302,8 @@ do { \ | |||
301 | " .long 2b \n" \ | 302 | " .long 2b \n" \ |
302 | "5: \n" \ | 303 | "5: \n" \ |
303 | " l32r %1, 4b \n" \ | 304 | " l32r %1, 4b \n" \ |
304 | " movi %0, %4 \n" \ | 305 | " movi %0, %4 \n" \ |
305 | " jx %1 \n" \ | 306 | " jx %1 \n" \ |
306 | " .previous \n" \ | 307 | " .previous \n" \ |
307 | " .section __ex_table,\"a\" \n" \ | 308 | " .section __ex_table,\"a\" \n" \ |
308 | " .long 1b, 5b \n" \ | 309 | " .long 1b, 5b \n" \ |
@@ -334,13 +335,13 @@ extern long __get_user_bad(void); | |||
334 | do { \ | 335 | do { \ |
335 | int __cb; \ | 336 | int __cb; \ |
336 | retval = 0; \ | 337 | retval = 0; \ |
337 | switch (size) { \ | 338 | switch (size) { \ |
338 | case 1: __get_user_asm(x,ptr,retval,1,"l8ui",__cb); break; \ | 339 | case 1: __get_user_asm(x,ptr,retval,1,"l8ui",__cb); break; \ |
339 | case 2: __get_user_asm(x,ptr,retval,2,"l16ui",__cb); break; \ | 340 | case 2: __get_user_asm(x,ptr,retval,2,"l16ui",__cb); break; \ |
340 | case 4: __get_user_asm(x,ptr,retval,4,"l32i",__cb); break; \ | 341 | case 4: __get_user_asm(x,ptr,retval,4,"l32i",__cb); break; \ |
341 | case 8: retval = __copy_from_user(&x,ptr,8); break; \ | 342 | case 8: retval = __copy_from_user(&x,ptr,8); break; \ |
342 | default: (x) = __get_user_bad(); \ | 343 | default: (x) = __get_user_bad(); \ |
343 | } \ | 344 | } \ |
344 | } while (0) | 345 | } while (0) |
345 | 346 | ||
346 | 347 | ||
@@ -349,7 +350,7 @@ do { \ | |||
349 | * __check_align_* macros still work. | 350 | * __check_align_* macros still work. |
350 | */ | 351 | */ |
351 | #define __get_user_asm(x, addr, err, align, insn, cb) \ | 352 | #define __get_user_asm(x, addr, err, align, insn, cb) \ |
352 | __asm__ __volatile__( \ | 353 | __asm__ __volatile__( \ |
353 | __check_align_##align \ | 354 | __check_align_##align \ |
354 | "1: "insn" %2, %3, 0 \n" \ | 355 | "1: "insn" %2, %3, 0 \n" \ |
355 | "2: \n" \ | 356 | "2: \n" \ |
@@ -360,8 +361,8 @@ do { \ | |||
360 | "5: \n" \ | 361 | "5: \n" \ |
361 | " l32r %1, 4b \n" \ | 362 | " l32r %1, 4b \n" \ |
362 | " movi %2, 0 \n" \ | 363 | " movi %2, 0 \n" \ |
363 | " movi %0, %4 \n" \ | 364 | " movi %0, %4 \n" \ |
364 | " jx %1 \n" \ | 365 | " jx %1 \n" \ |
365 | " .previous \n" \ | 366 | " .previous \n" \ |
366 | " .section __ex_table,\"a\" \n" \ | 367 | " .section __ex_table,\"a\" \n" \ |
367 | " .long 1b, 5b \n" \ | 368 | " .long 1b, 5b \n" \ |
@@ -421,8 +422,10 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n) | |||
421 | 422 | ||
422 | #define copy_to_user(to,from,n) __generic_copy_to_user((to),(from),(n)) | 423 | #define copy_to_user(to,from,n) __generic_copy_to_user((to),(from),(n)) |
423 | #define copy_from_user(to,from,n) __generic_copy_from_user((to),(from),(n)) | 424 | #define copy_from_user(to,from,n) __generic_copy_from_user((to),(from),(n)) |
424 | #define __copy_to_user(to,from,n) __generic_copy_to_user_nocheck((to),(from),(n)) | 425 | #define __copy_to_user(to,from,n) \ |
425 | #define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n)) | 426 | __generic_copy_to_user_nocheck((to),(from),(n)) |
427 | #define __copy_from_user(to,from,n) \ | ||
428 | __generic_copy_from_user_nocheck((to),(from),(n)) | ||
426 | #define __copy_to_user_inatomic __copy_to_user | 429 | #define __copy_to_user_inatomic __copy_to_user |
427 | #define __copy_from_user_inatomic __copy_from_user | 430 | #define __copy_from_user_inatomic __copy_from_user |
428 | 431 | ||
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile index f36cef5a62ff..c3a59d992ac0 100644 --- a/arch/xtensa/kernel/Makefile +++ b/arch/xtensa/kernel/Makefile | |||
@@ -23,13 +23,13 @@ obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o | |||
23 | # | 23 | # |
24 | # Replicate rules in scripts/Makefile.build | 24 | # Replicate rules in scripts/Makefile.build |
25 | 25 | ||
26 | sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g' \ | 26 | sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g' \ |
27 | -e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g' \ | 27 | -e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g' \ |
28 | -e 's/\*(\(\.text\.[a-z]*\))/*(\1.literal \1)/g' | 28 | -e 's/\*(\(\.text\.[a-z]*\))/*(\1.literal \1)/g' |
29 | 29 | ||
30 | quiet_cmd__cpp_lds_S = LDS $@ | 30 | quiet_cmd__cpp_lds_S = LDS $@ |
31 | cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \ | 31 | cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \ |
32 | | sed $(sed-y) >$@ | 32 | | sed $(sed-y) >$@ |
33 | 33 | ||
34 | $(obj)/vmlinux.lds: $(src)/vmlinux.lds.S FORCE | 34 | $(obj)/vmlinux.lds: $(src)/vmlinux.lds.S FORCE |
35 | $(call if_changed_dep,_cpp_lds_S) | 35 | $(call if_changed_dep,_cpp_lds_S) |
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S index 934ae58e2c79..aa2e87b8566a 100644 --- a/arch/xtensa/kernel/align.S +++ b/arch/xtensa/kernel/align.S | |||
@@ -442,7 +442,7 @@ ENTRY(fast_unaligned) | |||
442 | mov a1, a2 | 442 | mov a1, a2 |
443 | 443 | ||
444 | rsr a0, ps | 444 | rsr a0, ps |
445 | bbsi.l a2, PS_UM_BIT, 1f # jump if user mode | 445 | bbsi.l a2, PS_UM_BIT, 1f # jump if user mode |
446 | 446 | ||
447 | movi a0, _kernel_exception | 447 | movi a0, _kernel_exception |
448 | jx a0 | 448 | jx a0 |
@@ -450,6 +450,6 @@ ENTRY(fast_unaligned) | |||
450 | 1: movi a0, _user_exception | 450 | 1: movi a0, _user_exception |
451 | jx a0 | 451 | jx a0 |
452 | 452 | ||
453 | ENDPROC(fast_unaligned) | ||
453 | 454 | ||
454 | #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */ | 455 | #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */ |
455 | |||
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index 7dc3f9157185..0701fad170db 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c | |||
@@ -41,6 +41,7 @@ int main(void) | |||
41 | DEFINE(PT_SAR, offsetof (struct pt_regs, sar)); | 41 | DEFINE(PT_SAR, offsetof (struct pt_regs, sar)); |
42 | DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel)); | 42 | DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel)); |
43 | DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); | 43 | DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); |
44 | DEFINE(PT_SCOMPARE1, offsetof(struct pt_regs, scompare1)); | ||
44 | DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); | 45 | DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); |
45 | DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0])); | 46 | DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0])); |
46 | DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1])); | 47 | DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1])); |
@@ -91,7 +92,8 @@ int main(void) | |||
91 | #endif | 92 | #endif |
92 | DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user)); | 93 | DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user)); |
93 | DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t)); | 94 | DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t)); |
94 | DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds)); | 95 | DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, \ |
96 | thread.current_ds)); | ||
95 | 97 | ||
96 | /* struct mm_struct */ | 98 | /* struct mm_struct */ |
97 | DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users)); | 99 | DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users)); |
@@ -108,4 +110,3 @@ int main(void) | |||
108 | 110 | ||
109 | return 0; | 111 | return 0; |
110 | } | 112 | } |
111 | |||
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S index 54c3be313bfa..647657484866 100644 --- a/arch/xtensa/kernel/coprocessor.S +++ b/arch/xtensa/kernel/coprocessor.S | |||
@@ -43,10 +43,13 @@ | |||
43 | /* IO protection is currently unsupported. */ | 43 | /* IO protection is currently unsupported. */ |
44 | 44 | ||
45 | ENTRY(fast_io_protect) | 45 | ENTRY(fast_io_protect) |
46 | |||
46 | wsr a0, excsave1 | 47 | wsr a0, excsave1 |
47 | movi a0, unrecoverable_exception | 48 | movi a0, unrecoverable_exception |
48 | callx0 a0 | 49 | callx0 a0 |
49 | 50 | ||
51 | ENDPROC(fast_io_protect) | ||
52 | |||
50 | #if XTENSA_HAVE_COPROCESSORS | 53 | #if XTENSA_HAVE_COPROCESSORS |
51 | 54 | ||
52 | /* | 55 | /* |
@@ -139,6 +142,7 @@ ENTRY(fast_io_protect) | |||
139 | */ | 142 | */ |
140 | 143 | ||
141 | ENTRY(coprocessor_save) | 144 | ENTRY(coprocessor_save) |
145 | |||
142 | entry a1, 32 | 146 | entry a1, 32 |
143 | s32i a0, a1, 0 | 147 | s32i a0, a1, 0 |
144 | movi a0, .Lsave_cp_regs_jump_table | 148 | movi a0, .Lsave_cp_regs_jump_table |
@@ -150,7 +154,10 @@ ENTRY(coprocessor_save) | |||
150 | 1: l32i a0, a1, 0 | 154 | 1: l32i a0, a1, 0 |
151 | retw | 155 | retw |
152 | 156 | ||
157 | ENDPROC(coprocessor_save) | ||
158 | |||
153 | ENTRY(coprocessor_load) | 159 | ENTRY(coprocessor_load) |
160 | |||
154 | entry a1, 32 | 161 | entry a1, 32 |
155 | s32i a0, a1, 0 | 162 | s32i a0, a1, 0 |
156 | movi a0, .Lload_cp_regs_jump_table | 163 | movi a0, .Lload_cp_regs_jump_table |
@@ -162,8 +169,10 @@ ENTRY(coprocessor_load) | |||
162 | 1: l32i a0, a1, 0 | 169 | 1: l32i a0, a1, 0 |
163 | retw | 170 | retw |
164 | 171 | ||
172 | ENDPROC(coprocessor_load) | ||
173 | |||
165 | /* | 174 | /* |
166 | * coprocessor_flush(struct task_info*, index) | 175 | * coprocessor_flush(struct task_info*, index) |
167 | * a2 a3 | 176 | * a2 a3 |
168 | * coprocessor_restore(struct task_info*, index) | 177 | * coprocessor_restore(struct task_info*, index) |
169 | * a2 a3 | 178 | * a2 a3 |
@@ -178,6 +187,7 @@ ENTRY(coprocessor_load) | |||
178 | 187 | ||
179 | 188 | ||
180 | ENTRY(coprocessor_flush) | 189 | ENTRY(coprocessor_flush) |
190 | |||
181 | entry a1, 32 | 191 | entry a1, 32 |
182 | s32i a0, a1, 0 | 192 | s32i a0, a1, 0 |
183 | movi a0, .Lsave_cp_regs_jump_table | 193 | movi a0, .Lsave_cp_regs_jump_table |
@@ -191,6 +201,8 @@ ENTRY(coprocessor_flush) | |||
191 | 1: l32i a0, a1, 0 | 201 | 1: l32i a0, a1, 0 |
192 | retw | 202 | retw |
193 | 203 | ||
204 | ENDPROC(coprocessor_flush) | ||
205 | |||
194 | ENTRY(coprocessor_restore) | 206 | ENTRY(coprocessor_restore) |
195 | entry a1, 32 | 207 | entry a1, 32 |
196 | s32i a0, a1, 0 | 208 | s32i a0, a1, 0 |
@@ -205,6 +217,8 @@ ENTRY(coprocessor_restore) | |||
205 | 1: l32i a0, a1, 0 | 217 | 1: l32i a0, a1, 0 |
206 | retw | 218 | retw |
207 | 219 | ||
220 | ENDPROC(coprocessor_restore) | ||
221 | |||
208 | /* | 222 | /* |
209 | * Entry condition: | 223 | * Entry condition: |
210 | * | 224 | * |
@@ -220,10 +234,12 @@ ENTRY(coprocessor_restore) | |||
220 | */ | 234 | */ |
221 | 235 | ||
222 | ENTRY(fast_coprocessor_double) | 236 | ENTRY(fast_coprocessor_double) |
237 | |||
223 | wsr a0, excsave1 | 238 | wsr a0, excsave1 |
224 | movi a0, unrecoverable_exception | 239 | movi a0, unrecoverable_exception |
225 | callx0 a0 | 240 | callx0 a0 |
226 | 241 | ||
242 | ENDPROC(fast_coprocessor_double) | ||
227 | 243 | ||
228 | ENTRY(fast_coprocessor) | 244 | ENTRY(fast_coprocessor) |
229 | 245 | ||
@@ -327,9 +343,14 @@ ENTRY(fast_coprocessor) | |||
327 | 343 | ||
328 | rfe | 344 | rfe |
329 | 345 | ||
346 | ENDPROC(fast_coprocessor) | ||
347 | |||
330 | .data | 348 | .data |
349 | |||
331 | ENTRY(coprocessor_owner) | 350 | ENTRY(coprocessor_owner) |
351 | |||
332 | .fill XCHAL_CP_MAX, 4, 0 | 352 | .fill XCHAL_CP_MAX, 4, 0 |
333 | 353 | ||
334 | #endif /* XTENSA_HAVE_COPROCESSORS */ | 354 | END(coprocessor_owner) |
335 | 355 | ||
356 | #endif /* XTENSA_HAVE_COPROCESSORS */ | ||
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 90bfc1dbc13d..3777fec85e7c 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -219,6 +219,7 @@ _user_exception: | |||
219 | 219 | ||
220 | j common_exception | 220 | j common_exception |
221 | 221 | ||
222 | ENDPROC(user_exception) | ||
222 | 223 | ||
223 | /* | 224 | /* |
224 | * First-level exit handler for kernel exceptions | 225 | * First-level exit handler for kernel exceptions |
@@ -371,6 +372,13 @@ common_exception: | |||
371 | s32i a2, a1, PT_LBEG | 372 | s32i a2, a1, PT_LBEG |
372 | s32i a3, a1, PT_LEND | 373 | s32i a3, a1, PT_LEND |
373 | 374 | ||
375 | /* Save SCOMPARE1 */ | ||
376 | |||
377 | #if XCHAL_HAVE_S32C1I | ||
378 | rsr a2, scompare1 | ||
379 | s32i a2, a1, PT_SCOMPARE1 | ||
380 | #endif | ||
381 | |||
374 | /* Save optional registers. */ | 382 | /* Save optional registers. */ |
375 | 383 | ||
376 | save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT | 384 | save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT |
@@ -432,6 +440,12 @@ common_exception_return: | |||
432 | 440 | ||
433 | load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT | 441 | load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT |
434 | 442 | ||
443 | /* Restore SCOMPARE1 */ | ||
444 | |||
445 | #if XCHAL_HAVE_S32C1I | ||
446 | l32i a2, a1, PT_SCOMPARE1 | ||
447 | wsr a2, scompare1 | ||
448 | #endif | ||
435 | wsr a3, ps /* disable interrupts */ | 449 | wsr a3, ps /* disable interrupts */ |
436 | 450 | ||
437 | _bbci.l a3, PS_UM_BIT, kernel_exception_exit | 451 | _bbci.l a3, PS_UM_BIT, kernel_exception_exit |
@@ -641,6 +655,8 @@ common_exception_exit: | |||
641 | l32i a1, a1, PT_AREG1 | 655 | l32i a1, a1, PT_AREG1 |
642 | rfde | 656 | rfde |
643 | 657 | ||
658 | ENDPROC(kernel_exception) | ||
659 | |||
644 | /* | 660 | /* |
645 | * Debug exception handler. | 661 | * Debug exception handler. |
646 | * | 662 | * |
@@ -701,6 +717,7 @@ ENTRY(debug_exception) | |||
701 | /* Debug exception while in exception mode. */ | 717 | /* Debug exception while in exception mode. */ |
702 | 1: j 1b // FIXME!! | 718 | 1: j 1b // FIXME!! |
703 | 719 | ||
720 | ENDPROC(debug_exception) | ||
704 | 721 | ||
705 | /* | 722 | /* |
706 | * We get here in case of an unrecoverable exception. | 723 | * We get here in case of an unrecoverable exception. |
@@ -751,6 +768,7 @@ ENTRY(unrecoverable_exception) | |||
751 | 768 | ||
752 | 1: j 1b | 769 | 1: j 1b |
753 | 770 | ||
771 | ENDPROC(unrecoverable_exception) | ||
754 | 772 | ||
755 | /* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */ | 773 | /* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */ |
756 | 774 | ||
@@ -856,7 +874,7 @@ ENTRY(fast_alloca) | |||
856 | 874 | ||
857 | _bnei a0, 1, 1f # no 'movsp a1, ax': jump | 875 | _bnei a0, 1, 1f # no 'movsp a1, ax': jump |
858 | 876 | ||
859 | /* Move the save area. This implies the use of the L32E | 877 | /* Move the save area. This implies the use of the L32E |
860 | * and S32E instructions, because this move must be done with | 878 | * and S32E instructions, because this move must be done with |
861 | * the user's PS.RING privilege levels, not with ring 0 | 879 | * the user's PS.RING privilege levels, not with ring 0 |
862 | * (kernel's) privileges currently active with PS.EXCM | 880 | * (kernel's) privileges currently active with PS.EXCM |
@@ -929,6 +947,7 @@ ENTRY(fast_alloca) | |||
929 | l32i a2, a2, PT_AREG2 | 947 | l32i a2, a2, PT_AREG2 |
930 | rfe | 948 | rfe |
931 | 949 | ||
950 | ENDPROC(fast_alloca) | ||
932 | 951 | ||
933 | /* | 952 | /* |
934 | * fast system calls. | 953 | * fast system calls. |
@@ -966,6 +985,8 @@ ENTRY(fast_syscall_kernel) | |||
966 | 985 | ||
967 | j kernel_exception | 986 | j kernel_exception |
968 | 987 | ||
988 | ENDPROC(fast_syscall_kernel) | ||
989 | |||
969 | ENTRY(fast_syscall_user) | 990 | ENTRY(fast_syscall_user) |
970 | 991 | ||
971 | /* Skip syscall. */ | 992 | /* Skip syscall. */ |
@@ -983,19 +1004,21 @@ ENTRY(fast_syscall_user) | |||
983 | 1004 | ||
984 | j user_exception | 1005 | j user_exception |
985 | 1006 | ||
986 | ENTRY(fast_syscall_unrecoverable) | 1007 | ENDPROC(fast_syscall_user) |
987 | 1008 | ||
988 | /* Restore all states. */ | 1009 | ENTRY(fast_syscall_unrecoverable) |
989 | 1010 | ||
990 | l32i a0, a2, PT_AREG0 # restore a0 | 1011 | /* Restore all states. */ |
991 | xsr a2, depc # restore a2, depc | ||
992 | rsr a3, excsave1 | ||
993 | 1012 | ||
994 | wsr a0, excsave1 | 1013 | l32i a0, a2, PT_AREG0 # restore a0 |
995 | movi a0, unrecoverable_exception | 1014 | xsr a2, depc # restore a2, depc |
996 | callx0 a0 | 1015 | rsr a3, excsave1 |
997 | 1016 | ||
1017 | wsr a0, excsave1 | ||
1018 | movi a0, unrecoverable_exception | ||
1019 | callx0 a0 | ||
998 | 1020 | ||
1021 | ENDPROC(fast_syscall_unrecoverable) | ||
999 | 1022 | ||
1000 | /* | 1023 | /* |
1001 | * sysxtensa syscall handler | 1024 | * sysxtensa syscall handler |
@@ -1101,7 +1124,7 @@ CATCH | |||
1101 | movi a2, -EINVAL | 1124 | movi a2, -EINVAL |
1102 | rfe | 1125 | rfe |
1103 | 1126 | ||
1104 | 1127 | ENDPROC(fast_syscall_xtensa) | |
1105 | 1128 | ||
1106 | 1129 | ||
1107 | /* fast_syscall_spill_registers. | 1130 | /* fast_syscall_spill_registers. |
@@ -1160,6 +1183,8 @@ ENTRY(fast_syscall_spill_registers) | |||
1160 | movi a2, 0 | 1183 | movi a2, 0 |
1161 | rfe | 1184 | rfe |
1162 | 1185 | ||
1186 | ENDPROC(fast_syscall_spill_registers) | ||
1187 | |||
1163 | /* Fixup handler. | 1188 | /* Fixup handler. |
1164 | * | 1189 | * |
1165 | * We get here if the spill routine causes an exception, e.g. tlb miss. | 1190 | * We get here if the spill routine causes an exception, e.g. tlb miss. |
@@ -1228,9 +1253,9 @@ fast_syscall_spill_registers_fixup: | |||
1228 | 1253 | ||
1229 | movi a3, exc_table | 1254 | movi a3, exc_table |
1230 | rsr a0, exccause | 1255 | rsr a0, exccause |
1231 | addx4 a0, a0, a3 # find entry in table | 1256 | addx4 a0, a0, a3 # find entry in table |
1232 | l32i a0, a0, EXC_TABLE_FAST_USER # load handler | 1257 | l32i a0, a0, EXC_TABLE_FAST_USER # load handler |
1233 | jx a0 | 1258 | jx a0 |
1234 | 1259 | ||
1235 | fast_syscall_spill_registers_fixup_return: | 1260 | fast_syscall_spill_registers_fixup_return: |
1236 | 1261 | ||
@@ -1432,7 +1457,7 @@ ENTRY(_spill_registers) | |||
1432 | rsr a0, ps | 1457 | rsr a0, ps |
1433 | _bbci.l a0, PS_UM_BIT, 1f | 1458 | _bbci.l a0, PS_UM_BIT, 1f |
1434 | 1459 | ||
1435 | /* User space: Setup a dummy frame and kill application. | 1460 | /* User space: Setup a dummy frame and kill application. |
1436 | * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer. | 1461 | * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer. |
1437 | */ | 1462 | */ |
1438 | 1463 | ||
@@ -1464,6 +1489,8 @@ ENTRY(_spill_registers) | |||
1464 | callx0 a0 # should not return | 1489 | callx0 a0 # should not return |
1465 | 1: j 1b | 1490 | 1: j 1b |
1466 | 1491 | ||
1492 | ENDPROC(_spill_registers) | ||
1493 | |||
1467 | #ifdef CONFIG_MMU | 1494 | #ifdef CONFIG_MMU |
1468 | /* | 1495 | /* |
1469 | * We should never get here. Bail out! | 1496 | * We should never get here. Bail out! |
@@ -1475,6 +1502,8 @@ ENTRY(fast_second_level_miss_double_kernel) | |||
1475 | callx0 a0 # should not return | 1502 | callx0 a0 # should not return |
1476 | 1: j 1b | 1503 | 1: j 1b |
1477 | 1504 | ||
1505 | ENDPROC(fast_second_level_miss_double_kernel) | ||
1506 | |||
1478 | /* First-level entry handler for user, kernel, and double 2nd-level | 1507 | /* First-level entry handler for user, kernel, and double 2nd-level |
1479 | * TLB miss exceptions. Note that for now, user and kernel miss | 1508 | * TLB miss exceptions. Note that for now, user and kernel miss |
1480 | * exceptions share the same entry point and are handled identically. | 1509 | * exceptions share the same entry point and are handled identically. |
@@ -1682,6 +1711,7 @@ ENTRY(fast_second_level_miss) | |||
1682 | j _kernel_exception | 1711 | j _kernel_exception |
1683 | 1: j _user_exception | 1712 | 1: j _user_exception |
1684 | 1713 | ||
1714 | ENDPROC(fast_second_level_miss) | ||
1685 | 1715 | ||
1686 | /* | 1716 | /* |
1687 | * StoreProhibitedException | 1717 | * StoreProhibitedException |
@@ -1777,6 +1807,9 @@ ENTRY(fast_store_prohibited) | |||
1777 | bbsi.l a2, PS_UM_BIT, 1f | 1807 | bbsi.l a2, PS_UM_BIT, 1f |
1778 | j _kernel_exception | 1808 | j _kernel_exception |
1779 | 1: j _user_exception | 1809 | 1: j _user_exception |
1810 | |||
1811 | ENDPROC(fast_store_prohibited) | ||
1812 | |||
1780 | #endif /* CONFIG_MMU */ | 1813 | #endif /* CONFIG_MMU */ |
1781 | 1814 | ||
1782 | /* | 1815 | /* |
@@ -1787,6 +1820,7 @@ ENTRY(fast_store_prohibited) | |||
1787 | */ | 1820 | */ |
1788 | 1821 | ||
1789 | ENTRY(system_call) | 1822 | ENTRY(system_call) |
1823 | |||
1790 | entry a1, 32 | 1824 | entry a1, 32 |
1791 | 1825 | ||
1792 | /* regs->syscall = regs->areg[2] */ | 1826 | /* regs->syscall = regs->areg[2] */ |
@@ -1831,6 +1865,8 @@ ENTRY(system_call) | |||
1831 | callx4 a4 | 1865 | callx4 a4 |
1832 | retw | 1866 | retw |
1833 | 1867 | ||
1868 | ENDPROC(system_call) | ||
1869 | |||
1834 | 1870 | ||
1835 | /* | 1871 | /* |
1836 | * Task switch. | 1872 | * Task switch. |
@@ -1899,6 +1935,7 @@ ENTRY(_switch_to) | |||
1899 | 1935 | ||
1900 | retw | 1936 | retw |
1901 | 1937 | ||
1938 | ENDPROC(_switch_to) | ||
1902 | 1939 | ||
1903 | ENTRY(ret_from_fork) | 1940 | ENTRY(ret_from_fork) |
1904 | 1941 | ||
@@ -1914,6 +1951,8 @@ ENTRY(ret_from_fork) | |||
1914 | 1951 | ||
1915 | j common_exception_return | 1952 | j common_exception_return |
1916 | 1953 | ||
1954 | ENDPROC(ret_from_fork) | ||
1955 | |||
1917 | /* | 1956 | /* |
1918 | * Kernel thread creation helper | 1957 | * Kernel thread creation helper |
1919 | * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg | 1958 | * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg |
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index bdc50788f35e..91d9095284de 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/processor.h> | 18 | #include <asm/processor.h> |
19 | #include <asm/page.h> | 19 | #include <asm/page.h> |
20 | #include <asm/cacheasm.h> | 20 | #include <asm/cacheasm.h> |
21 | #include <asm/initialize_mmu.h> | ||
21 | 22 | ||
22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
23 | #include <linux/linkage.h> | 24 | #include <linux/linkage.h> |
@@ -47,16 +48,19 @@ | |||
47 | */ | 48 | */ |
48 | 49 | ||
49 | __HEAD | 50 | __HEAD |
50 | .globl _start | 51 | ENTRY(_start) |
51 | _start: _j 2f | 52 | |
53 | _j 2f | ||
52 | .align 4 | 54 | .align 4 |
53 | 1: .word _startup | 55 | 1: .word _startup |
54 | 2: l32r a0, 1b | 56 | 2: l32r a0, 1b |
55 | jx a0 | 57 | jx a0 |
56 | 58 | ||
59 | ENDPROC(_start) | ||
60 | |||
57 | .section .init.text, "ax" | 61 | .section .init.text, "ax" |
58 | .align 4 | 62 | |
59 | _startup: | 63 | ENTRY(_startup) |
60 | 64 | ||
61 | /* Disable interrupts and exceptions. */ | 65 | /* Disable interrupts and exceptions. */ |
62 | 66 | ||
@@ -107,7 +111,7 @@ _startup: | |||
107 | /* Disable all timers. */ | 111 | /* Disable all timers. */ |
108 | 112 | ||
109 | .set _index, 0 | 113 | .set _index, 0 |
110 | .rept XCHAL_NUM_TIMERS - 1 | 114 | .rept XCHAL_NUM_TIMERS |
111 | wsr a0, SREG_CCOMPARE + _index | 115 | wsr a0, SREG_CCOMPARE + _index |
112 | .set _index, _index + 1 | 116 | .set _index, _index + 1 |
113 | .endr | 117 | .endr |
@@ -120,7 +124,7 @@ _startup: | |||
120 | 124 | ||
121 | /* Disable coprocessors. */ | 125 | /* Disable coprocessors. */ |
122 | 126 | ||
123 | #if XCHAL_CP_NUM > 0 | 127 | #if XCHAL_HAVE_CP |
124 | wsr a0, cpenable | 128 | wsr a0, cpenable |
125 | #endif | 129 | #endif |
126 | 130 | ||
@@ -152,6 +156,8 @@ _startup: | |||
152 | 156 | ||
153 | isync | 157 | isync |
154 | 158 | ||
159 | initialize_mmu | ||
160 | |||
155 | /* Unpack data sections | 161 | /* Unpack data sections |
156 | * | 162 | * |
157 | * The linker script used to build the Linux kernel image | 163 | * The linker script used to build the Linux kernel image |
@@ -230,6 +236,7 @@ _startup: | |||
230 | should_never_return: | 236 | should_never_return: |
231 | j should_never_return | 237 | j should_never_return |
232 | 238 | ||
239 | ENDPROC(_startup) | ||
233 | 240 | ||
234 | /* | 241 | /* |
235 | * BSS section | 242 | * BSS section |
@@ -239,6 +246,8 @@ __PAGE_ALIGNED_BSS | |||
239 | #ifdef CONFIG_MMU | 246 | #ifdef CONFIG_MMU |
240 | ENTRY(swapper_pg_dir) | 247 | ENTRY(swapper_pg_dir) |
241 | .fill PAGE_SIZE, 1, 0 | 248 | .fill PAGE_SIZE, 1, 0 |
249 | END(swapper_pg_dir) | ||
242 | #endif | 250 | #endif |
243 | ENTRY(empty_zero_page) | 251 | ENTRY(empty_zero_page) |
244 | .fill PAGE_SIZE, 1, 0 | 252 | .fill PAGE_SIZE, 1, 0 |
253 | END(empty_zero_page) | ||
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index a6ce3e563739..6f4f9749cff7 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/kernel_stat.h> | 20 | #include <linux/kernel_stat.h> |
21 | #include <linux/irqdomain.h> | ||
22 | #include <linux/of.h> | ||
21 | 23 | ||
22 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
23 | #include <asm/platform.h> | 25 | #include <asm/platform.h> |
@@ -26,19 +28,22 @@ static unsigned int cached_irq_mask; | |||
26 | 28 | ||
27 | atomic_t irq_err_count; | 29 | atomic_t irq_err_count; |
28 | 30 | ||
31 | static struct irq_domain *root_domain; | ||
32 | |||
29 | /* | 33 | /* |
30 | * do_IRQ handles all normal device IRQ's (the special | 34 | * do_IRQ handles all normal device IRQ's (the special |
31 | * SMP cross-CPU interrupts have their own specific | 35 | * SMP cross-CPU interrupts have their own specific |
32 | * handlers). | 36 | * handlers). |
33 | */ | 37 | */ |
34 | 38 | ||
35 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs) | 39 | asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) |
36 | { | 40 | { |
37 | struct pt_regs *old_regs = set_irq_regs(regs); | 41 | struct pt_regs *old_regs = set_irq_regs(regs); |
42 | int irq = irq_find_mapping(root_domain, hwirq); | ||
38 | 43 | ||
39 | if (irq >= NR_IRQS) { | 44 | if (hwirq >= NR_IRQS) { |
40 | printk(KERN_EMERG "%s: cannot handle IRQ %d\n", | 45 | printk(KERN_EMERG "%s: cannot handle IRQ %d\n", |
41 | __func__, irq); | 46 | __func__, hwirq); |
42 | } | 47 | } |
43 | 48 | ||
44 | irq_enter(); | 49 | irq_enter(); |
@@ -71,40 +76,39 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
71 | 76 | ||
72 | static void xtensa_irq_mask(struct irq_data *d) | 77 | static void xtensa_irq_mask(struct irq_data *d) |
73 | { | 78 | { |
74 | cached_irq_mask &= ~(1 << d->irq); | 79 | cached_irq_mask &= ~(1 << d->hwirq); |
75 | set_sr (cached_irq_mask, intenable); | 80 | set_sr (cached_irq_mask, intenable); |
76 | } | 81 | } |
77 | 82 | ||
78 | static void xtensa_irq_unmask(struct irq_data *d) | 83 | static void xtensa_irq_unmask(struct irq_data *d) |
79 | { | 84 | { |
80 | cached_irq_mask |= 1 << d->irq; | 85 | cached_irq_mask |= 1 << d->hwirq; |
81 | set_sr (cached_irq_mask, intenable); | 86 | set_sr (cached_irq_mask, intenable); |
82 | } | 87 | } |
83 | 88 | ||
84 | static void xtensa_irq_enable(struct irq_data *d) | 89 | static void xtensa_irq_enable(struct irq_data *d) |
85 | { | 90 | { |
86 | variant_irq_enable(d->irq); | 91 | variant_irq_enable(d->hwirq); |
87 | xtensa_irq_unmask(d); | 92 | xtensa_irq_unmask(d); |
88 | } | 93 | } |
89 | 94 | ||
90 | static void xtensa_irq_disable(struct irq_data *d) | 95 | static void xtensa_irq_disable(struct irq_data *d) |
91 | { | 96 | { |
92 | xtensa_irq_mask(d); | 97 | xtensa_irq_mask(d); |
93 | variant_irq_disable(d->irq); | 98 | variant_irq_disable(d->hwirq); |
94 | } | 99 | } |
95 | 100 | ||
96 | static void xtensa_irq_ack(struct irq_data *d) | 101 | static void xtensa_irq_ack(struct irq_data *d) |
97 | { | 102 | { |
98 | set_sr(1 << d->irq, intclear); | 103 | set_sr(1 << d->hwirq, intclear); |
99 | } | 104 | } |
100 | 105 | ||
101 | static int xtensa_irq_retrigger(struct irq_data *d) | 106 | static int xtensa_irq_retrigger(struct irq_data *d) |
102 | { | 107 | { |
103 | set_sr (1 << d->irq, INTSET); | 108 | set_sr(1 << d->hwirq, intset); |
104 | return 1; | 109 | return 1; |
105 | } | 110 | } |
106 | 111 | ||
107 | |||
108 | static struct irq_chip xtensa_irq_chip = { | 112 | static struct irq_chip xtensa_irq_chip = { |
109 | .name = "xtensa", | 113 | .name = "xtensa", |
110 | .irq_enable = xtensa_irq_enable, | 114 | .irq_enable = xtensa_irq_enable, |
@@ -115,37 +119,99 @@ static struct irq_chip xtensa_irq_chip = { | |||
115 | .irq_retrigger = xtensa_irq_retrigger, | 119 | .irq_retrigger = xtensa_irq_retrigger, |
116 | }; | 120 | }; |
117 | 121 | ||
118 | void __init init_IRQ(void) | 122 | static int xtensa_irq_map(struct irq_domain *d, unsigned int irq, |
123 | irq_hw_number_t hw) | ||
119 | { | 124 | { |
120 | int index; | 125 | u32 mask = 1 << hw; |
121 | 126 | ||
122 | for (index = 0; index < XTENSA_NR_IRQS; index++) { | 127 | if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) { |
123 | int mask = 1 << index; | 128 | irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, |
124 | 129 | handle_simple_irq, "level"); | |
125 | if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) | 130 | irq_set_status_flags(irq, IRQ_LEVEL); |
126 | irq_set_chip_and_handler(index, &xtensa_irq_chip, | 131 | } else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) { |
127 | handle_simple_irq); | 132 | irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, |
133 | handle_edge_irq, "edge"); | ||
134 | irq_clear_status_flags(irq, IRQ_LEVEL); | ||
135 | } else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) { | ||
136 | irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, | ||
137 | handle_level_irq, "level"); | ||
138 | irq_set_status_flags(irq, IRQ_LEVEL); | ||
139 | } else if (mask & XCHAL_INTTYPE_MASK_TIMER) { | ||
140 | irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, | ||
141 | handle_edge_irq, "edge"); | ||
142 | irq_clear_status_flags(irq, IRQ_LEVEL); | ||
143 | } else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */ | ||
144 | /* XCHAL_INTTYPE_MASK_NMI */ | ||
145 | |||
146 | irq_set_chip_and_handler_name(irq, &xtensa_irq_chip, | ||
147 | handle_level_irq, "level"); | ||
148 | irq_set_status_flags(irq, IRQ_LEVEL); | ||
149 | } | ||
150 | return 0; | ||
151 | } | ||
128 | 152 | ||
129 | else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) | 153 | static unsigned map_ext_irq(unsigned ext_irq) |
130 | irq_set_chip_and_handler(index, &xtensa_irq_chip, | 154 | { |
131 | handle_edge_irq); | 155 | unsigned mask = XCHAL_INTTYPE_MASK_EXTERN_EDGE | |
156 | XCHAL_INTTYPE_MASK_EXTERN_LEVEL; | ||
157 | unsigned i; | ||
132 | 158 | ||
133 | else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) | 159 | for (i = 0; mask; ++i, mask >>= 1) { |
134 | irq_set_chip_and_handler(index, &xtensa_irq_chip, | 160 | if ((mask & 1) && ext_irq-- == 0) |
135 | handle_level_irq); | 161 | return i; |
162 | } | ||
163 | return XCHAL_NUM_INTERRUPTS; | ||
164 | } | ||
136 | 165 | ||
137 | else if (mask & XCHAL_INTTYPE_MASK_TIMER) | 166 | /* |
138 | irq_set_chip_and_handler(index, &xtensa_irq_chip, | 167 | * Device Tree IRQ specifier translation function which works with one or |
139 | handle_edge_irq); | 168 | * two cell bindings. First cell value maps directly to the hwirq number. |
169 | * Second cell if present specifies whether hwirq number is external (1) or | ||
170 | * internal (0). | ||
171 | */ | ||
172 | int xtensa_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, | ||
173 | const u32 *intspec, unsigned int intsize, | ||
174 | unsigned long *out_hwirq, unsigned int *out_type) | ||
175 | { | ||
176 | if (WARN_ON(intsize < 1 || intsize > 2)) | ||
177 | return -EINVAL; | ||
178 | if (intsize == 2 && intspec[1] == 1) { | ||
179 | unsigned int_irq = map_ext_irq(intspec[0]); | ||
180 | if (int_irq < XCHAL_NUM_INTERRUPTS) | ||
181 | *out_hwirq = int_irq; | ||
182 | else | ||
183 | return -EINVAL; | ||
184 | } else { | ||
185 | *out_hwirq = intspec[0]; | ||
186 | } | ||
187 | *out_type = IRQ_TYPE_NONE; | ||
188 | return 0; | ||
189 | } | ||
140 | 190 | ||
141 | else /* XCHAL_INTTYPE_MASK_WRITE_ERROR */ | 191 | static const struct irq_domain_ops xtensa_irq_domain_ops = { |
142 | /* XCHAL_INTTYPE_MASK_NMI */ | 192 | .xlate = xtensa_irq_domain_xlate, |
193 | .map = xtensa_irq_map, | ||
194 | }; | ||
143 | 195 | ||
144 | irq_set_chip_and_handler(index, &xtensa_irq_chip, | 196 | void __init init_IRQ(void) |
145 | handle_level_irq); | 197 | { |
146 | } | 198 | struct device_node *intc = NULL; |
147 | 199 | ||
148 | cached_irq_mask = 0; | 200 | cached_irq_mask = 0; |
201 | set_sr(~0, intclear); | ||
202 | |||
203 | #ifdef CONFIG_OF | ||
204 | /* The interrupt controller device node is mandatory */ | ||
205 | intc = of_find_compatible_node(NULL, NULL, "xtensa,pic"); | ||
206 | BUG_ON(!intc); | ||
207 | |||
208 | root_domain = irq_domain_add_linear(intc, NR_IRQS, | ||
209 | &xtensa_irq_domain_ops, NULL); | ||
210 | #else | ||
211 | root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0, | ||
212 | &xtensa_irq_domain_ops, NULL); | ||
213 | #endif | ||
214 | irq_set_default_host(root_domain); | ||
149 | 215 | ||
150 | variant_init_irq(); | 216 | variant_init_irq(); |
151 | } | 217 | } |
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c index 451dda928c93..b715237bae61 100644 --- a/arch/xtensa/kernel/module.c +++ b/arch/xtensa/kernel/module.c | |||
@@ -53,7 +53,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, | |||
53 | struct module *mod) | 53 | struct module *mod) |
54 | { | 54 | { |
55 | unsigned int i; | 55 | unsigned int i; |
56 | Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; | 56 | Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; |
57 | Elf32_Sym *sym; | 57 | Elf32_Sym *sym; |
58 | unsigned char *location; | 58 | unsigned char *location; |
59 | uint32_t value; | 59 | uint32_t value; |
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index 97230e46cbe7..44bf21c3769a 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c | |||
@@ -44,4 +44,3 @@ _F(void, calibrate_ccount, (void), | |||
44 | ccount_per_jiffy = 10 * (1000000UL/HZ); | 44 | ccount_per_jiffy = 10 * (1000000UL/HZ); |
45 | }); | 45 | }); |
46 | #endif | 46 | #endif |
47 | |||
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 1accf28da5f5..0dd5784416d3 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -108,7 +108,7 @@ void coprocessor_flush_all(struct thread_info *ti) | |||
108 | 108 | ||
109 | void cpu_idle(void) | 109 | void cpu_idle(void) |
110 | { | 110 | { |
111 | local_irq_enable(); | 111 | local_irq_enable(); |
112 | 112 | ||
113 | /* endless idle loop with no priority at all */ | 113 | /* endless idle loop with no priority at all */ |
114 | while (1) { | 114 | while (1) { |
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 33eea4c16f12..61fb2e9e9035 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c | |||
@@ -154,7 +154,7 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs) | |||
154 | coprocessor_flush_all(ti); | 154 | coprocessor_flush_all(ti); |
155 | coprocessor_release_all(ti); | 155 | coprocessor_release_all(ti); |
156 | 156 | ||
157 | ret |= __copy_from_user(&ti->xtregs_cp, &xtregs->cp0, | 157 | ret |= __copy_from_user(&ti->xtregs_cp, &xtregs->cp0, |
158 | sizeof(xtregs_coprocessor_t)); | 158 | sizeof(xtregs_coprocessor_t)); |
159 | #endif | 159 | #endif |
160 | ret |= __copy_from_user(®s->xtregs_opt, &xtregs->opt, | 160 | ret |= __copy_from_user(®s->xtregs_opt, &xtregs->opt, |
@@ -343,4 +343,3 @@ void do_syscall_trace_leave(struct pt_regs *regs) | |||
343 | && (current->ptrace & PT_PTRACED)) | 343 | && (current->ptrace & PT_PTRACED)) |
344 | do_syscall_trace(); | 344 | do_syscall_trace(); |
345 | } | 345 | } |
346 | |||
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index b237988ba6d7..24c1a57abb40 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -22,6 +22,11 @@ | |||
22 | #include <linux/bootmem.h> | 22 | #include <linux/bootmem.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | 24 | ||
25 | #ifdef CONFIG_OF | ||
26 | #include <linux/of_fdt.h> | ||
27 | #include <linux/of_platform.h> | ||
28 | #endif | ||
29 | |||
25 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) | 30 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) |
26 | # include <linux/console.h> | 31 | # include <linux/console.h> |
27 | #endif | 32 | #endif |
@@ -42,6 +47,7 @@ | |||
42 | #include <asm/page.h> | 47 | #include <asm/page.h> |
43 | #include <asm/setup.h> | 48 | #include <asm/setup.h> |
44 | #include <asm/param.h> | 49 | #include <asm/param.h> |
50 | #include <asm/traps.h> | ||
45 | 51 | ||
46 | #include <platform/hardware.h> | 52 | #include <platform/hardware.h> |
47 | 53 | ||
@@ -64,6 +70,11 @@ int initrd_is_mapped = 0; | |||
64 | extern int initrd_below_start_ok; | 70 | extern int initrd_below_start_ok; |
65 | #endif | 71 | #endif |
66 | 72 | ||
73 | #ifdef CONFIG_OF | ||
74 | extern u32 __dtb_start[]; | ||
75 | void *dtb_start = __dtb_start; | ||
76 | #endif | ||
77 | |||
67 | unsigned char aux_device_present; | 78 | unsigned char aux_device_present; |
68 | extern unsigned long loops_per_jiffy; | 79 | extern unsigned long loops_per_jiffy; |
69 | 80 | ||
@@ -83,6 +94,8 @@ extern void init_mmu(void); | |||
83 | static inline void init_mmu(void) { } | 94 | static inline void init_mmu(void) { } |
84 | #endif | 95 | #endif |
85 | 96 | ||
97 | extern int mem_reserve(unsigned long, unsigned long, int); | ||
98 | extern void bootmem_init(void); | ||
86 | extern void zones_init(void); | 99 | extern void zones_init(void); |
87 | 100 | ||
88 | /* | 101 | /* |
@@ -104,28 +117,33 @@ typedef struct tagtable { | |||
104 | 117 | ||
105 | /* parse current tag */ | 118 | /* parse current tag */ |
106 | 119 | ||
107 | static int __init parse_tag_mem(const bp_tag_t *tag) | 120 | static int __init add_sysmem_bank(unsigned long type, unsigned long start, |
121 | unsigned long end) | ||
108 | { | 122 | { |
109 | meminfo_t *mi = (meminfo_t*)(tag->data); | ||
110 | |||
111 | if (mi->type != MEMORY_TYPE_CONVENTIONAL) | ||
112 | return -1; | ||
113 | |||
114 | if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) { | 123 | if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) { |
115 | printk(KERN_WARNING | 124 | printk(KERN_WARNING |
116 | "Ignoring memory bank 0x%08lx size %ldKB\n", | 125 | "Ignoring memory bank 0x%08lx size %ldKB\n", |
117 | (unsigned long)mi->start, | 126 | start, end - start); |
118 | (unsigned long)mi->end - (unsigned long)mi->start); | ||
119 | return -EINVAL; | 127 | return -EINVAL; |
120 | } | 128 | } |
121 | sysmem.bank[sysmem.nr_banks].type = mi->type; | 129 | sysmem.bank[sysmem.nr_banks].type = type; |
122 | sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start); | 130 | sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(start); |
123 | sysmem.bank[sysmem.nr_banks].end = mi->end & PAGE_MASK; | 131 | sysmem.bank[sysmem.nr_banks].end = end & PAGE_MASK; |
124 | sysmem.nr_banks++; | 132 | sysmem.nr_banks++; |
125 | 133 | ||
126 | return 0; | 134 | return 0; |
127 | } | 135 | } |
128 | 136 | ||
137 | static int __init parse_tag_mem(const bp_tag_t *tag) | ||
138 | { | ||
139 | meminfo_t *mi = (meminfo_t *)(tag->data); | ||
140 | |||
141 | if (mi->type != MEMORY_TYPE_CONVENTIONAL) | ||
142 | return -1; | ||
143 | |||
144 | return add_sysmem_bank(mi->type, mi->start, mi->end); | ||
145 | } | ||
146 | |||
129 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); | 147 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); |
130 | 148 | ||
131 | #ifdef CONFIG_BLK_DEV_INITRD | 149 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -142,12 +160,31 @@ static int __init parse_tag_initrd(const bp_tag_t* tag) | |||
142 | 160 | ||
143 | __tagtable(BP_TAG_INITRD, parse_tag_initrd); | 161 | __tagtable(BP_TAG_INITRD, parse_tag_initrd); |
144 | 162 | ||
163 | #ifdef CONFIG_OF | ||
164 | |||
165 | static int __init parse_tag_fdt(const bp_tag_t *tag) | ||
166 | { | ||
167 | dtb_start = (void *)(tag->data[0]); | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | __tagtable(BP_TAG_FDT, parse_tag_fdt); | ||
172 | |||
173 | void __init early_init_dt_setup_initrd_arch(unsigned long start, | ||
174 | unsigned long end) | ||
175 | { | ||
176 | initrd_start = (void *)__va(start); | ||
177 | initrd_end = (void *)__va(end); | ||
178 | initrd_below_start_ok = 1; | ||
179 | } | ||
180 | |||
181 | #endif /* CONFIG_OF */ | ||
182 | |||
145 | #endif /* CONFIG_BLK_DEV_INITRD */ | 183 | #endif /* CONFIG_BLK_DEV_INITRD */ |
146 | 184 | ||
147 | static int __init parse_tag_cmdline(const bp_tag_t* tag) | 185 | static int __init parse_tag_cmdline(const bp_tag_t* tag) |
148 | { | 186 | { |
149 | strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE); | 187 | strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE); |
150 | command_line[COMMAND_LINE_SIZE - 1] = '\0'; | ||
151 | return 0; | 188 | return 0; |
152 | } | 189 | } |
153 | 190 | ||
@@ -185,6 +222,58 @@ static int __init parse_bootparam(const bp_tag_t* tag) | |||
185 | return 0; | 222 | return 0; |
186 | } | 223 | } |
187 | 224 | ||
225 | #ifdef CONFIG_OF | ||
226 | |||
227 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | ||
228 | { | ||
229 | size &= PAGE_MASK; | ||
230 | add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size); | ||
231 | } | ||
232 | |||
233 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | ||
234 | { | ||
235 | return __alloc_bootmem(size, align, 0); | ||
236 | } | ||
237 | |||
238 | void __init early_init_devtree(void *params) | ||
239 | { | ||
240 | /* Setup flat device-tree pointer */ | ||
241 | initial_boot_params = params; | ||
242 | |||
243 | /* Retrieve various informations from the /chosen node of the | ||
244 | * device-tree, including the platform type, initrd location and | ||
245 | * size, TCE reserve, and more ... | ||
246 | */ | ||
247 | if (!command_line[0]) | ||
248 | of_scan_flat_dt(early_init_dt_scan_chosen, command_line); | ||
249 | |||
250 | /* Scan memory nodes and rebuild MEMBLOCKs */ | ||
251 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
252 | if (sysmem.nr_banks == 0) | ||
253 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
254 | } | ||
255 | |||
256 | static void __init copy_devtree(void) | ||
257 | { | ||
258 | void *alloc = early_init_dt_alloc_memory_arch( | ||
259 | be32_to_cpu(initial_boot_params->totalsize), 0); | ||
260 | if (alloc) { | ||
261 | memcpy(alloc, initial_boot_params, | ||
262 | be32_to_cpu(initial_boot_params->totalsize)); | ||
263 | initial_boot_params = alloc; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static int __init xtensa_device_probe(void) | ||
268 | { | ||
269 | of_platform_populate(NULL, NULL, NULL, NULL); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | device_initcall(xtensa_device_probe); | ||
274 | |||
275 | #endif /* CONFIG_OF */ | ||
276 | |||
188 | /* | 277 | /* |
189 | * Initialize architecture. (Early stage) | 278 | * Initialize architecture. (Early stage) |
190 | */ | 279 | */ |
@@ -193,14 +282,14 @@ void __init init_arch(bp_tag_t *bp_start) | |||
193 | { | 282 | { |
194 | sysmem.nr_banks = 0; | 283 | sysmem.nr_banks = 0; |
195 | 284 | ||
196 | #ifdef CONFIG_CMDLINE_BOOL | ||
197 | strcpy(command_line, default_command_line); | ||
198 | #endif | ||
199 | |||
200 | /* Parse boot parameters */ | 285 | /* Parse boot parameters */ |
201 | 286 | ||
202 | if (bp_start) | 287 | if (bp_start) |
203 | parse_bootparam(bp_start); | 288 | parse_bootparam(bp_start); |
289 | |||
290 | #ifdef CONFIG_OF | ||
291 | early_init_devtree(dtb_start); | ||
292 | #endif | ||
204 | 293 | ||
205 | if (sysmem.nr_banks == 0) { | 294 | if (sysmem.nr_banks == 0) { |
206 | sysmem.nr_banks = 1; | 295 | sysmem.nr_banks = 1; |
@@ -209,6 +298,11 @@ void __init init_arch(bp_tag_t *bp_start) | |||
209 | + PLATFORM_DEFAULT_MEM_SIZE; | 298 | + PLATFORM_DEFAULT_MEM_SIZE; |
210 | } | 299 | } |
211 | 300 | ||
301 | #ifdef CONFIG_CMDLINE_BOOL | ||
302 | if (!command_line[0]) | ||
303 | strlcpy(command_line, default_command_line, COMMAND_LINE_SIZE); | ||
304 | #endif | ||
305 | |||
212 | /* Early hook for platforms */ | 306 | /* Early hook for platforms */ |
213 | 307 | ||
214 | platform_init(bp_start); | 308 | platform_init(bp_start); |
@@ -235,15 +329,130 @@ extern char _UserExceptionVector_text_end; | |||
235 | extern char _DoubleExceptionVector_literal_start; | 329 | extern char _DoubleExceptionVector_literal_start; |
236 | extern char _DoubleExceptionVector_text_end; | 330 | extern char _DoubleExceptionVector_text_end; |
237 | 331 | ||
238 | void __init setup_arch(char **cmdline_p) | 332 | |
333 | #ifdef CONFIG_S32C1I_SELFTEST | ||
334 | #if XCHAL_HAVE_S32C1I | ||
335 | |||
336 | static int __initdata rcw_word, rcw_probe_pc, rcw_exc; | ||
337 | |||
338 | /* | ||
339 | * Basic atomic compare-and-swap, that records PC of S32C1I for probing. | ||
340 | * | ||
341 | * If *v == cmp, set *v = set. Return previous *v. | ||
342 | */ | ||
343 | static inline int probed_compare_swap(int *v, int cmp, int set) | ||
344 | { | ||
345 | int tmp; | ||
346 | |||
347 | __asm__ __volatile__( | ||
348 | " movi %1, 1f\n" | ||
349 | " s32i %1, %4, 0\n" | ||
350 | " wsr %2, scompare1\n" | ||
351 | "1: s32c1i %0, %3, 0\n" | ||
352 | : "=a" (set), "=&a" (tmp) | ||
353 | : "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set) | ||
354 | : "memory" | ||
355 | ); | ||
356 | return set; | ||
357 | } | ||
358 | |||
359 | /* Handle probed exception */ | ||
360 | |||
361 | void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause) | ||
362 | { | ||
363 | if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ | ||
364 | regs->pc += 3; /* skip the s32c1i instruction */ | ||
365 | rcw_exc = exccause; | ||
366 | } else { | ||
367 | do_unhandled(regs, exccause); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /* Simple test of S32C1I (soc bringup assist) */ | ||
372 | |||
373 | void __init check_s32c1i(void) | ||
374 | { | ||
375 | int n, cause1, cause2; | ||
376 | void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ | ||
377 | |||
378 | rcw_probe_pc = 0; | ||
379 | handbus = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, | ||
380 | do_probed_exception); | ||
381 | handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, | ||
382 | do_probed_exception); | ||
383 | handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, | ||
384 | do_probed_exception); | ||
385 | |||
386 | /* First try an S32C1I that does not store: */ | ||
387 | rcw_exc = 0; | ||
388 | rcw_word = 1; | ||
389 | n = probed_compare_swap(&rcw_word, 0, 2); | ||
390 | cause1 = rcw_exc; | ||
391 | |||
392 | /* took exception? */ | ||
393 | if (cause1 != 0) { | ||
394 | /* unclean exception? */ | ||
395 | if (n != 2 || rcw_word != 1) | ||
396 | panic("S32C1I exception error"); | ||
397 | } else if (rcw_word != 1 || n != 1) { | ||
398 | panic("S32C1I compare error"); | ||
399 | } | ||
400 | |||
401 | /* Then an S32C1I that stores: */ | ||
402 | rcw_exc = 0; | ||
403 | rcw_word = 0x1234567; | ||
404 | n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde); | ||
405 | cause2 = rcw_exc; | ||
406 | |||
407 | if (cause2 != 0) { | ||
408 | /* unclean exception? */ | ||
409 | if (n != 0xabcde || rcw_word != 0x1234567) | ||
410 | panic("S32C1I exception error (b)"); | ||
411 | } else if (rcw_word != 0xabcde || n != 0x1234567) { | ||
412 | panic("S32C1I store error"); | ||
413 | } | ||
414 | |||
415 | /* Verify consistency of exceptions: */ | ||
416 | if (cause1 || cause2) { | ||
417 | pr_warn("S32C1I took exception %d, %d\n", cause1, cause2); | ||
418 | /* If emulation of S32C1I upon bus error gets implemented, | ||
419 | we can get rid of this panic for single core (not SMP) */ | ||
420 | panic("S32C1I exceptions not currently supported"); | ||
421 | } | ||
422 | if (cause1 != cause2) | ||
423 | panic("inconsistent S32C1I exceptions"); | ||
424 | |||
425 | trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); | ||
426 | trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); | ||
427 | trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); | ||
428 | } | ||
429 | |||
430 | #else /* XCHAL_HAVE_S32C1I */ | ||
431 | |||
432 | /* This condition should not occur with a commercially deployed processor. | ||
433 | Display reminder for early engr test or demo chips / FPGA bitstreams */ | ||
434 | void __init check_s32c1i(void) | ||
435 | { | ||
436 | pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); | ||
437 | } | ||
438 | |||
439 | #endif /* XCHAL_HAVE_S32C1I */ | ||
440 | #else /* CONFIG_S32C1I_SELFTEST */ | ||
441 | |||
442 | void __init check_s32c1i(void) | ||
239 | { | 443 | { |
240 | extern int mem_reserve(unsigned long, unsigned long, int); | 444 | } |
241 | extern void bootmem_init(void); | 445 | |
446 | #endif /* CONFIG_S32C1I_SELFTEST */ | ||
242 | 447 | ||
243 | memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | 448 | |
244 | boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; | 449 | void __init setup_arch(char **cmdline_p) |
450 | { | ||
451 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | ||
245 | *cmdline_p = command_line; | 452 | *cmdline_p = command_line; |
246 | 453 | ||
454 | check_s32c1i(); | ||
455 | |||
247 | /* Reserve some memory regions */ | 456 | /* Reserve some memory regions */ |
248 | 457 | ||
249 | #ifdef CONFIG_BLK_DEV_INITRD | 458 | #ifdef CONFIG_BLK_DEV_INITRD |
@@ -251,7 +460,7 @@ void __init setup_arch(char **cmdline_p) | |||
251 | initrd_is_mapped = mem_reserve(__pa(initrd_start), | 460 | initrd_is_mapped = mem_reserve(__pa(initrd_start), |
252 | __pa(initrd_end), 0); | 461 | __pa(initrd_end), 0); |
253 | initrd_below_start_ok = 1; | 462 | initrd_below_start_ok = 1; |
254 | } else { | 463 | } else { |
255 | initrd_start = 0; | 464 | initrd_start = 0; |
256 | } | 465 | } |
257 | #endif | 466 | #endif |
@@ -275,8 +484,12 @@ void __init setup_arch(char **cmdline_p) | |||
275 | 484 | ||
276 | bootmem_init(); | 485 | bootmem_init(); |
277 | 486 | ||
278 | platform_setup(cmdline_p); | 487 | #ifdef CONFIG_OF |
488 | copy_devtree(); | ||
489 | unflatten_device_tree(); | ||
490 | #endif | ||
279 | 491 | ||
492 | platform_setup(cmdline_p); | ||
280 | 493 | ||
281 | paging_init(); | 494 | paging_init(); |
282 | zones_init(); | 495 | zones_init(); |
@@ -326,7 +539,7 @@ c_show(struct seq_file *f, void *slot) | |||
326 | "core ID\t\t: " XCHAL_CORE_ID "\n" | 539 | "core ID\t\t: " XCHAL_CORE_ID "\n" |
327 | "build ID\t: 0x%x\n" | 540 | "build ID\t: 0x%x\n" |
328 | "byte order\t: %s\n" | 541 | "byte order\t: %s\n" |
329 | "cpu MHz\t\t: %lu.%02lu\n" | 542 | "cpu MHz\t\t: %lu.%02lu\n" |
330 | "bogomips\t: %lu.%02lu\n", | 543 | "bogomips\t: %lu.%02lu\n", |
331 | XCHAL_BUILD_UNIQUE_ID, | 544 | XCHAL_BUILD_UNIQUE_ID, |
332 | XCHAL_HAVE_BE ? "big" : "little", | 545 | XCHAL_HAVE_BE ? "big" : "little", |
@@ -381,6 +594,9 @@ c_show(struct seq_file *f, void *slot) | |||
381 | #if XCHAL_HAVE_FP | 594 | #if XCHAL_HAVE_FP |
382 | "fpu " | 595 | "fpu " |
383 | #endif | 596 | #endif |
597 | #if XCHAL_HAVE_S32C1I | ||
598 | "s32c1i " | ||
599 | #endif | ||
384 | "\n"); | 600 | "\n"); |
385 | 601 | ||
386 | /* Registers. */ | 602 | /* Registers. */ |
@@ -412,7 +628,7 @@ c_show(struct seq_file *f, void *slot) | |||
412 | "icache size\t: %d\n" | 628 | "icache size\t: %d\n" |
413 | "icache flags\t: " | 629 | "icache flags\t: " |
414 | #if XCHAL_ICACHE_LINE_LOCKABLE | 630 | #if XCHAL_ICACHE_LINE_LOCKABLE |
415 | "lock" | 631 | "lock " |
416 | #endif | 632 | #endif |
417 | "\n" | 633 | "\n" |
418 | "dcache line size: %d\n" | 634 | "dcache line size: %d\n" |
@@ -420,10 +636,10 @@ c_show(struct seq_file *f, void *slot) | |||
420 | "dcache size\t: %d\n" | 636 | "dcache size\t: %d\n" |
421 | "dcache flags\t: " | 637 | "dcache flags\t: " |
422 | #if XCHAL_DCACHE_IS_WRITEBACK | 638 | #if XCHAL_DCACHE_IS_WRITEBACK |
423 | "writeback" | 639 | "writeback " |
424 | #endif | 640 | #endif |
425 | #if XCHAL_DCACHE_LINE_LOCKABLE | 641 | #if XCHAL_DCACHE_LINE_LOCKABLE |
426 | "lock" | 642 | "lock " |
427 | #endif | 643 | #endif |
428 | "\n", | 644 | "\n", |
429 | XCHAL_ICACHE_LINESIZE, | 645 | XCHAL_ICACHE_LINESIZE, |
@@ -465,4 +681,3 @@ const struct seq_operations cpuinfo_op = | |||
465 | }; | 681 | }; |
466 | 682 | ||
467 | #endif /* CONFIG_PROC_FS */ | 683 | #endif /* CONFIG_PROC_FS */ |
468 | |||
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 63c566f627bc..de34d6be91cd 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c | |||
@@ -212,7 +212,7 @@ restore_sigcontext(struct pt_regs *regs, struct rt_sigframe __user *frame) | |||
212 | if (err) | 212 | if (err) |
213 | return err; | 213 | return err; |
214 | 214 | ||
215 | /* The signal handler may have used coprocessors in which | 215 | /* The signal handler may have used coprocessors in which |
216 | * case they are still enabled. We disable them to force a | 216 | * case they are still enabled. We disable them to force a |
217 | * reloading of the original task's CP state by the lazy | 217 | * reloading of the original task's CP state by the lazy |
218 | * context-switching mechanisms of CP exception handling. | 218 | * context-switching mechanisms of CP exception handling. |
@@ -396,7 +396,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
396 | */ | 396 | */ |
397 | 397 | ||
398 | /* Set up registers for signal handler */ | 398 | /* Set up registers for signal handler */ |
399 | start_thread(regs, (unsigned long) ka->sa.sa_handler, | 399 | start_thread(regs, (unsigned long) ka->sa.sa_handler, |
400 | (unsigned long) frame); | 400 | (unsigned long) frame); |
401 | 401 | ||
402 | /* Set up a stack frame for a call4 | 402 | /* Set up a stack frame for a call4 |
@@ -424,9 +424,9 @@ give_sigsegv: | |||
424 | return -EFAULT; | 424 | return -EFAULT; |
425 | } | 425 | } |
426 | 426 | ||
427 | asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, | 427 | asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, |
428 | stack_t __user *uoss, | 428 | stack_t __user *uoss, |
429 | long a2, long a3, long a4, long a5, | 429 | long a2, long a3, long a4, long a5, |
430 | struct pt_regs *regs) | 430 | struct pt_regs *regs) |
431 | { | 431 | { |
432 | return do_sigaltstack(uss, uoss, regs->areg[1]); | 432 | return do_sigaltstack(uss, uoss, regs->areg[1]); |
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index 5702065f472a..54fa8425cee2 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c | |||
@@ -52,4 +52,3 @@ asmlinkage long xtensa_fadvise64_64(int fd, int advice, | |||
52 | { | 52 | { |
53 | return sys_fadvise64_64(fd, offset, len, advice); | 53 | return sys_fadvise64_64(fd, offset, len, advice); |
54 | } | 54 | } |
55 | |||
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index ac62f9cf1e10..ffb474104311 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/profile.h> | 23 | #include <linux/profile.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/irqdomain.h> | ||
25 | 26 | ||
26 | #include <asm/timex.h> | 27 | #include <asm/timex.h> |
27 | #include <asm/platform.h> | 28 | #include <asm/platform.h> |
@@ -31,7 +32,7 @@ unsigned long ccount_per_jiffy; /* per 1/HZ */ | |||
31 | unsigned long nsec_per_ccount; /* nsec per ccount increment */ | 32 | unsigned long nsec_per_ccount; /* nsec per ccount increment */ |
32 | #endif | 33 | #endif |
33 | 34 | ||
34 | static cycle_t ccount_read(void) | 35 | static cycle_t ccount_read(struct clocksource *cs) |
35 | { | 36 | { |
36 | return (cycle_t)get_ccount(); | 37 | return (cycle_t)get_ccount(); |
37 | } | 38 | } |
@@ -52,6 +53,7 @@ static struct irqaction timer_irqaction = { | |||
52 | 53 | ||
53 | void __init time_init(void) | 54 | void __init time_init(void) |
54 | { | 55 | { |
56 | unsigned int irq; | ||
55 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 57 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
56 | printk("Calibrating CPU frequency "); | 58 | printk("Calibrating CPU frequency "); |
57 | platform_calibrate_ccount(); | 59 | platform_calibrate_ccount(); |
@@ -62,7 +64,8 @@ void __init time_init(void) | |||
62 | 64 | ||
63 | /* Initialize the linux timer interrupt. */ | 65 | /* Initialize the linux timer interrupt. */ |
64 | 66 | ||
65 | setup_irq(LINUX_TIMER_INT, &timer_irqaction); | 67 | irq = irq_create_mapping(NULL, LINUX_TIMER_INT); |
68 | setup_irq(irq, &timer_irqaction); | ||
66 | set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); | 69 | set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); |
67 | } | 70 | } |
68 | 71 | ||
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 5caf2b64d43a..01e0111bf787 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c | |||
@@ -293,6 +293,17 @@ do_debug(struct pt_regs *regs) | |||
293 | } | 293 | } |
294 | 294 | ||
295 | 295 | ||
296 | /* Set exception C handler - for temporary use when probing exceptions */ | ||
297 | |||
298 | void * __init trap_set_handler(int cause, void *handler) | ||
299 | { | ||
300 | unsigned long *entry = &exc_table[EXC_TABLE_DEFAULT / 4 + cause]; | ||
301 | void *previous = (void *)*entry; | ||
302 | *entry = (unsigned long)handler; | ||
303 | return previous; | ||
304 | } | ||
305 | |||
306 | |||
296 | /* | 307 | /* |
297 | * Initialize dispatch tables. | 308 | * Initialize dispatch tables. |
298 | * | 309 | * |
@@ -397,7 +408,8 @@ static inline void spill_registers(void) | |||
397 | "wsr a13, sar\n\t" | 408 | "wsr a13, sar\n\t" |
398 | "wsr a14, ps\n\t" | 409 | "wsr a14, ps\n\t" |
399 | :: "a" (&a0), "a" (&ps) | 410 | :: "a" (&a0), "a" (&ps) |
400 | : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory"); | 411 | : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", |
412 | "memory"); | ||
401 | } | 413 | } |
402 | 414 | ||
403 | void show_trace(struct task_struct *task, unsigned long *sp) | 415 | void show_trace(struct task_struct *task, unsigned long *sp) |
@@ -452,7 +464,7 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
452 | 464 | ||
453 | if (!sp) | 465 | if (!sp) |
454 | sp = stack_pointer(task); | 466 | sp = stack_pointer(task); |
455 | stack = sp; | 467 | stack = sp; |
456 | 468 | ||
457 | printk("\nStack: "); | 469 | printk("\nStack: "); |
458 | 470 | ||
@@ -523,5 +535,3 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
523 | 535 | ||
524 | do_exit(err); | 536 | do_exit(err); |
525 | } | 537 | } |
526 | |||
527 | |||
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index 4462c1e595c2..68df35f66ce3 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S | |||
@@ -79,6 +79,8 @@ ENTRY(_UserExceptionVector) | |||
79 | l32i a0, a0, EXC_TABLE_FAST_USER # load handler | 79 | l32i a0, a0, EXC_TABLE_FAST_USER # load handler |
80 | jx a0 | 80 | jx a0 |
81 | 81 | ||
82 | ENDPROC(_UserExceptionVector) | ||
83 | |||
82 | /* | 84 | /* |
83 | * Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0) | 85 | * Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0) |
84 | * | 86 | * |
@@ -103,6 +105,7 @@ ENTRY(_KernelExceptionVector) | |||
103 | l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address | 105 | l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address |
104 | jx a0 | 106 | jx a0 |
105 | 107 | ||
108 | ENDPROC(_KernelExceptionVector) | ||
106 | 109 | ||
107 | /* | 110 | /* |
108 | * Double exception vector (Exceptions with PS.EXCM == 1) | 111 | * Double exception vector (Exceptions with PS.EXCM == 1) |
@@ -225,7 +228,13 @@ ENTRY(_DoubleExceptionVector) | |||
225 | /* Window overflow/underflow exception. Get stack pointer. */ | 228 | /* Window overflow/underflow exception. Get stack pointer. */ |
226 | 229 | ||
227 | mov a3, a2 | 230 | mov a3, a2 |
228 | movi a2, exc_table | 231 | /* This explicit literal and the following references to it are made |
232 | * in order to fit DoubleExceptionVector.literals into the available | ||
233 | * 16-byte gap before DoubleExceptionVector.text in the absence of | ||
234 | * link time relaxation. See kernel/vmlinux.lds.S | ||
235 | */ | ||
236 | .literal .Lexc_table, exc_table | ||
237 | l32r a2, .Lexc_table | ||
229 | l32i a2, a2, EXC_TABLE_KSTK | 238 | l32i a2, a2, EXC_TABLE_KSTK |
230 | 239 | ||
231 | /* Check for overflow/underflow exception, jump if overflow. */ | 240 | /* Check for overflow/underflow exception, jump if overflow. */ |
@@ -255,7 +264,7 @@ ENTRY(_DoubleExceptionVector) | |||
255 | s32i a0, a2, PT_AREG0 | 264 | s32i a0, a2, PT_AREG0 |
256 | 265 | ||
257 | wsr a3, excsave1 # save a3 | 266 | wsr a3, excsave1 # save a3 |
258 | movi a3, exc_table | 267 | l32r a3, .Lexc_table |
259 | 268 | ||
260 | rsr a0, exccause | 269 | rsr a0, exccause |
261 | s32i a0, a2, PT_DEPC # mark it as a regular exception | 270 | s32i a0, a2, PT_DEPC # mark it as a regular exception |
@@ -267,7 +276,7 @@ ENTRY(_DoubleExceptionVector) | |||
267 | 276 | ||
268 | /* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */ | 277 | /* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */ |
269 | 278 | ||
270 | movi a3, exc_table | 279 | l32r a3, .Lexc_table |
271 | s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable | 280 | s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable |
272 | 281 | ||
273 | /* Enter critical section. */ | 282 | /* Enter critical section. */ |
@@ -296,7 +305,7 @@ ENTRY(_DoubleExceptionVector) | |||
296 | 305 | ||
297 | /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */ | 306 | /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */ |
298 | 307 | ||
299 | movi a3, exc_table | 308 | l32r a3, .Lexc_table |
300 | rsr a0, exccause | 309 | rsr a0, exccause |
301 | addx4 a0, a0, a3 | 310 | addx4 a0, a0, a3 |
302 | l32i a0, a0, EXC_TABLE_FAST_USER | 311 | l32i a0, a0, EXC_TABLE_FAST_USER |
@@ -338,6 +347,7 @@ ENTRY(_DoubleExceptionVector) | |||
338 | 347 | ||
339 | .end literal_prefix | 348 | .end literal_prefix |
340 | 349 | ||
350 | ENDPROC(_DoubleExceptionVector) | ||
341 | 351 | ||
342 | /* | 352 | /* |
343 | * Debug interrupt vector | 353 | * Debug interrupt vector |
@@ -349,9 +359,11 @@ ENTRY(_DoubleExceptionVector) | |||
349 | .section .DebugInterruptVector.text, "ax" | 359 | .section .DebugInterruptVector.text, "ax" |
350 | 360 | ||
351 | ENTRY(_DebugInterruptVector) | 361 | ENTRY(_DebugInterruptVector) |
362 | |||
352 | xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL | 363 | xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL |
353 | jx a0 | 364 | jx a0 |
354 | 365 | ||
366 | ENDPROC(_DebugInterruptVector) | ||
355 | 367 | ||
356 | 368 | ||
357 | /* Window overflow and underflow handlers. | 369 | /* Window overflow and underflow handlers. |
@@ -363,38 +375,43 @@ ENTRY(_DebugInterruptVector) | |||
363 | * we try to access any page that would cause a page fault early. | 375 | * we try to access any page that would cause a page fault early. |
364 | */ | 376 | */ |
365 | 377 | ||
378 | #define ENTRY_ALIGN64(name) \ | ||
379 | .globl name; \ | ||
380 | .align 64; \ | ||
381 | name: | ||
382 | |||
366 | .section .WindowVectors.text, "ax" | 383 | .section .WindowVectors.text, "ax" |
367 | 384 | ||
368 | 385 | ||
369 | /* 4-Register Window Overflow Vector (Handler) */ | 386 | /* 4-Register Window Overflow Vector (Handler) */ |
370 | 387 | ||
371 | .align 64 | 388 | ENTRY_ALIGN64(_WindowOverflow4) |
372 | .global _WindowOverflow4 | 389 | |
373 | _WindowOverflow4: | ||
374 | s32e a0, a5, -16 | 390 | s32e a0, a5, -16 |
375 | s32e a1, a5, -12 | 391 | s32e a1, a5, -12 |
376 | s32e a2, a5, -8 | 392 | s32e a2, a5, -8 |
377 | s32e a3, a5, -4 | 393 | s32e a3, a5, -4 |
378 | rfwo | 394 | rfwo |
379 | 395 | ||
396 | ENDPROC(_WindowOverflow4) | ||
397 | |||
380 | 398 | ||
381 | /* 4-Register Window Underflow Vector (Handler) */ | 399 | /* 4-Register Window Underflow Vector (Handler) */ |
382 | 400 | ||
383 | .align 64 | 401 | ENTRY_ALIGN64(_WindowUnderflow4) |
384 | .global _WindowUnderflow4 | 402 | |
385 | _WindowUnderflow4: | ||
386 | l32e a0, a5, -16 | 403 | l32e a0, a5, -16 |
387 | l32e a1, a5, -12 | 404 | l32e a1, a5, -12 |
388 | l32e a2, a5, -8 | 405 | l32e a2, a5, -8 |
389 | l32e a3, a5, -4 | 406 | l32e a3, a5, -4 |
390 | rfwu | 407 | rfwu |
391 | 408 | ||
409 | ENDPROC(_WindowUnderflow4) | ||
392 | 410 | ||
393 | /* 8-Register Window Overflow Vector (Handler) */ | 411 | /* 8-Register Window Overflow Vector (Handler) */ |
394 | 412 | ||
395 | .align 64 | 413 | ENTRY_ALIGN64(_WindowOverflow8) |
396 | .global _WindowOverflow8 | 414 | |
397 | _WindowOverflow8: | ||
398 | s32e a0, a9, -16 | 415 | s32e a0, a9, -16 |
399 | l32e a0, a1, -12 | 416 | l32e a0, a1, -12 |
400 | s32e a2, a9, -8 | 417 | s32e a2, a9, -8 |
@@ -406,11 +423,12 @@ _WindowOverflow8: | |||
406 | s32e a7, a0, -20 | 423 | s32e a7, a0, -20 |
407 | rfwo | 424 | rfwo |
408 | 425 | ||
426 | ENDPROC(_WindowOverflow8) | ||
427 | |||
409 | /* 8-Register Window Underflow Vector (Handler) */ | 428 | /* 8-Register Window Underflow Vector (Handler) */ |
410 | 429 | ||
411 | .align 64 | 430 | ENTRY_ALIGN64(_WindowUnderflow8) |
412 | .global _WindowUnderflow8 | 431 | |
413 | _WindowUnderflow8: | ||
414 | l32e a1, a9, -12 | 432 | l32e a1, a9, -12 |
415 | l32e a0, a9, -16 | 433 | l32e a0, a9, -16 |
416 | l32e a7, a1, -12 | 434 | l32e a7, a1, -12 |
@@ -422,12 +440,12 @@ _WindowUnderflow8: | |||
422 | l32e a7, a7, -20 | 440 | l32e a7, a7, -20 |
423 | rfwu | 441 | rfwu |
424 | 442 | ||
443 | ENDPROC(_WindowUnderflow8) | ||
425 | 444 | ||
426 | /* 12-Register Window Overflow Vector (Handler) */ | 445 | /* 12-Register Window Overflow Vector (Handler) */ |
427 | 446 | ||
428 | .align 64 | 447 | ENTRY_ALIGN64(_WindowOverflow12) |
429 | .global _WindowOverflow12 | 448 | |
430 | _WindowOverflow12: | ||
431 | s32e a0, a13, -16 | 449 | s32e a0, a13, -16 |
432 | l32e a0, a1, -12 | 450 | l32e a0, a1, -12 |
433 | s32e a1, a13, -12 | 451 | s32e a1, a13, -12 |
@@ -443,11 +461,12 @@ _WindowOverflow12: | |||
443 | s32e a11, a0, -20 | 461 | s32e a11, a0, -20 |
444 | rfwo | 462 | rfwo |
445 | 463 | ||
464 | ENDPROC(_WindowOverflow12) | ||
465 | |||
446 | /* 12-Register Window Underflow Vector (Handler) */ | 466 | /* 12-Register Window Underflow Vector (Handler) */ |
447 | 467 | ||
448 | .align 64 | 468 | ENTRY_ALIGN64(_WindowUnderflow12) |
449 | .global _WindowUnderflow12 | 469 | |
450 | _WindowUnderflow12: | ||
451 | l32e a1, a13, -12 | 470 | l32e a1, a13, -12 |
452 | l32e a0, a13, -16 | 471 | l32e a0, a13, -16 |
453 | l32e a11, a1, -12 | 472 | l32e a11, a1, -12 |
@@ -463,6 +482,6 @@ _WindowUnderflow12: | |||
463 | l32e a11, a11, -20 | 482 | l32e a11, a11, -20 |
464 | rfwu | 483 | rfwu |
465 | 484 | ||
466 | .text | 485 | ENDPROC(_WindowUnderflow12) |
467 | |||
468 | 486 | ||
487 | .text | ||
diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S index df397f932d0e..4eb573d2720e 100644 --- a/arch/xtensa/lib/checksum.S +++ b/arch/xtensa/lib/checksum.S | |||
@@ -41,10 +41,11 @@ | |||
41 | 41 | ||
42 | .text | 42 | .text |
43 | ENTRY(csum_partial) | 43 | ENTRY(csum_partial) |
44 | /* | 44 | |
45 | * Experiments with Ethernet and SLIP connections show that buf | 45 | /* |
46 | * is aligned on either a 2-byte or 4-byte boundary. | 46 | * Experiments with Ethernet and SLIP connections show that buf |
47 | */ | 47 | * is aligned on either a 2-byte or 4-byte boundary. |
48 | */ | ||
48 | entry sp, 32 | 49 | entry sp, 32 |
49 | extui a5, a2, 0, 2 | 50 | extui a5, a2, 0, 2 |
50 | bnez a5, 8f /* branch if 2-byte aligned */ | 51 | bnez a5, 8f /* branch if 2-byte aligned */ |
@@ -170,7 +171,7 @@ ENTRY(csum_partial) | |||
170 | 3: | 171 | 3: |
171 | j 5b /* branch to handle the remaining byte */ | 172 | j 5b /* branch to handle the remaining byte */ |
172 | 173 | ||
173 | 174 | ENDPROC(csum_partial) | |
174 | 175 | ||
175 | /* | 176 | /* |
176 | * Copy from ds while checksumming, otherwise like csum_partial | 177 | * Copy from ds while checksumming, otherwise like csum_partial |
@@ -211,6 +212,7 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, | |||
211 | */ | 212 | */ |
212 | 213 | ||
213 | ENTRY(csum_partial_copy_generic) | 214 | ENTRY(csum_partial_copy_generic) |
215 | |||
214 | entry sp, 32 | 216 | entry sp, 32 |
215 | mov a12, a3 | 217 | mov a12, a3 |
216 | mov a11, a4 | 218 | mov a11, a4 |
@@ -367,6 +369,8 @@ DST( s8i a8, a3, 1 ) | |||
367 | 6: | 369 | 6: |
368 | j 4b /* process the possible trailing odd byte */ | 370 | j 4b /* process the possible trailing odd byte */ |
369 | 371 | ||
372 | ENDPROC(csum_partial_copy_generic) | ||
373 | |||
370 | 374 | ||
371 | # Exception handler: | 375 | # Exception handler: |
372 | .section .fixup, "ax" | 376 | .section .fixup, "ax" |
@@ -406,4 +410,3 @@ DST( s8i a8, a3, 1 ) | |||
406 | retw | 410 | retw |
407 | 411 | ||
408 | .previous | 412 | .previous |
409 | |||
diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S index c48b80acb5f0..b1c219acabe7 100644 --- a/arch/xtensa/lib/memcopy.S +++ b/arch/xtensa/lib/memcopy.S | |||
@@ -210,8 +210,10 @@ memcpy: | |||
210 | _beqz a4, .Ldone # avoid loading anything for zero-length copies | 210 | _beqz a4, .Ldone # avoid loading anything for zero-length copies |
211 | # copy 16 bytes per iteration for word-aligned dst and unaligned src | 211 | # copy 16 bytes per iteration for word-aligned dst and unaligned src |
212 | ssa8 a3 # set shift amount from byte offset | 212 | ssa8 a3 # set shift amount from byte offset |
213 | #define SIM_CHECKS_ALIGNMENT 1 /* set to 1 when running on ISS (simulator) with the | 213 | |
214 | lint or ferret client, or 0 to save a few cycles */ | 214 | /* set to 1 when running on ISS (simulator) with the |
215 | lint or ferret client, or 0 to save a few cycles */ | ||
216 | #define SIM_CHECKS_ALIGNMENT 1 | ||
215 | #if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT | 217 | #if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT |
216 | and a11, a3, a8 # save unalignment offset for below | 218 | and a11, a3, a8 # save unalignment offset for below |
217 | sub a3, a3, a11 # align a3 | 219 | sub a3, a3, a11 # align a3 |
diff --git a/arch/xtensa/lib/pci-auto.c b/arch/xtensa/lib/pci-auto.c index a71733ae1193..34d05abbd921 100644 --- a/arch/xtensa/lib/pci-auto.c +++ b/arch/xtensa/lib/pci-auto.c | |||
@@ -241,8 +241,8 @@ int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus) | |||
241 | unsigned char header_type; | 241 | unsigned char header_type; |
242 | struct pci_dev *dev = &pciauto_dev; | 242 | struct pci_dev *dev = &pciauto_dev; |
243 | 243 | ||
244 | pciauto_dev.bus = &pciauto_bus; | 244 | pciauto_dev.bus = &pciauto_bus; |
245 | pciauto_dev.sysdata = pci_ctrl; | 245 | pciauto_dev.sysdata = pci_ctrl; |
246 | pciauto_bus.ops = pci_ctrl->ops; | 246 | pciauto_bus.ops = pci_ctrl->ops; |
247 | 247 | ||
248 | /* | 248 | /* |
@@ -345,8 +345,3 @@ int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus) | |||
345 | } | 345 | } |
346 | return sub_bus; | 346 | return sub_bus; |
347 | } | 347 | } |
348 | |||
349 | |||
350 | |||
351 | |||
352 | |||
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S index 9f603cdaaa68..1ad0ecf45368 100644 --- a/arch/xtensa/lib/strncpy_user.S +++ b/arch/xtensa/lib/strncpy_user.S | |||
@@ -166,7 +166,7 @@ __strncpy_user: | |||
166 | retw | 166 | retw |
167 | .Lz1: # byte 1 is zero | 167 | .Lz1: # byte 1 is zero |
168 | #ifdef __XTENSA_EB__ | 168 | #ifdef __XTENSA_EB__ |
169 | extui a9, a9, 16, 16 | 169 | extui a9, a9, 16, 16 |
170 | #endif /* __XTENSA_EB__ */ | 170 | #endif /* __XTENSA_EB__ */ |
171 | EX(s16i, a9, a11, 0, fixup_s) | 171 | EX(s16i, a9, a11, 0, fixup_s) |
172 | addi a11, a11, 1 # advance dst pointer | 172 | addi a11, a11, 1 # advance dst pointer |
@@ -174,7 +174,7 @@ __strncpy_user: | |||
174 | retw | 174 | retw |
175 | .Lz2: # byte 2 is zero | 175 | .Lz2: # byte 2 is zero |
176 | #ifdef __XTENSA_EB__ | 176 | #ifdef __XTENSA_EB__ |
177 | extui a9, a9, 16, 16 | 177 | extui a9, a9, 16, 16 |
178 | #endif /* __XTENSA_EB__ */ | 178 | #endif /* __XTENSA_EB__ */ |
179 | EX(s16i, a9, a11, 0, fixup_s) | 179 | EX(s16i, a9, a11, 0, fixup_s) |
180 | movi a9, 0 | 180 | movi a9, 0 |
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S index 23f2a89816a1..4c03b1e581e9 100644 --- a/arch/xtensa/lib/strnlen_user.S +++ b/arch/xtensa/lib/strnlen_user.S | |||
@@ -145,4 +145,3 @@ __strnlen_user: | |||
145 | lenfixup: | 145 | lenfixup: |
146 | movi a2, 0 | 146 | movi a2, 0 |
147 | retw | 147 | retw |
148 | |||
diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S index 46d60314bb16..ace1892a875e 100644 --- a/arch/xtensa/lib/usercopy.S +++ b/arch/xtensa/lib/usercopy.S | |||
@@ -318,4 +318,3 @@ l_fixup: | |||
318 | /* Ignore memset return value in a6. */ | 318 | /* Ignore memset return value in a6. */ |
319 | /* a2 still contains bytes not copied. */ | 319 | /* a2 still contains bytes not copied. */ |
320 | retw | 320 | retw |
321 | |||
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index 85df4655d326..81edeab82d17 100644 --- a/arch/xtensa/mm/cache.c +++ b/arch/xtensa/mm/cache.c | |||
@@ -118,7 +118,7 @@ void flush_dcache_page(struct page *page) | |||
118 | * For now, flush the whole cache. FIXME?? | 118 | * For now, flush the whole cache. FIXME?? |
119 | */ | 119 | */ |
120 | 120 | ||
121 | void flush_cache_range(struct vm_area_struct* vma, | 121 | void flush_cache_range(struct vm_area_struct* vma, |
122 | unsigned long start, unsigned long end) | 122 | unsigned long start, unsigned long end) |
123 | { | 123 | { |
124 | __flush_invalidate_dcache_all(); | 124 | __flush_invalidate_dcache_all(); |
@@ -133,7 +133,7 @@ void flush_cache_range(struct vm_area_struct* vma, | |||
133 | */ | 133 | */ |
134 | 134 | ||
135 | void flush_cache_page(struct vm_area_struct* vma, unsigned long address, | 135 | void flush_cache_page(struct vm_area_struct* vma, unsigned long address, |
136 | unsigned long pfn) | 136 | unsigned long pfn) |
137 | { | 137 | { |
138 | /* Note that we have to use the 'alias' address to avoid multi-hit */ | 138 | /* Note that we have to use the 'alias' address to avoid multi-hit */ |
139 | 139 | ||
@@ -166,14 +166,14 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep) | |||
166 | 166 | ||
167 | if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) { | 167 | if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) { |
168 | 168 | ||
169 | unsigned long vaddr = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK); | ||
170 | unsigned long paddr = (unsigned long) page_address(page); | 169 | unsigned long paddr = (unsigned long) page_address(page); |
171 | unsigned long phys = page_to_phys(page); | 170 | unsigned long phys = page_to_phys(page); |
171 | unsigned long tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK); | ||
172 | 172 | ||
173 | __flush_invalidate_dcache_page(paddr); | 173 | __flush_invalidate_dcache_page(paddr); |
174 | 174 | ||
175 | __flush_invalidate_dcache_page_alias(vaddr, phys); | 175 | __flush_invalidate_dcache_page_alias(tmp, phys); |
176 | __invalidate_icache_page_alias(vaddr, phys); | 176 | __invalidate_icache_page_alias(tmp, phys); |
177 | 177 | ||
178 | clear_bit(PG_arch_1, &page->flags); | 178 | clear_bit(PG_arch_1, &page->flags); |
179 | } | 179 | } |
@@ -195,7 +195,7 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep) | |||
195 | 195 | ||
196 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK | 196 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK |
197 | 197 | ||
198 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | 198 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, |
199 | unsigned long vaddr, void *dst, const void *src, | 199 | unsigned long vaddr, void *dst, const void *src, |
200 | unsigned long len) | 200 | unsigned long len) |
201 | { | 201 | { |
@@ -205,8 +205,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | |||
205 | /* Flush and invalidate user page if aliased. */ | 205 | /* Flush and invalidate user page if aliased. */ |
206 | 206 | ||
207 | if (alias) { | 207 | if (alias) { |
208 | unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); | 208 | unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); |
209 | __flush_invalidate_dcache_page_alias(temp, phys); | 209 | __flush_invalidate_dcache_page_alias(t, phys); |
210 | } | 210 | } |
211 | 211 | ||
212 | /* Copy data */ | 212 | /* Copy data */ |
@@ -219,12 +219,11 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | |||
219 | */ | 219 | */ |
220 | 220 | ||
221 | if (alias) { | 221 | if (alias) { |
222 | unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); | 222 | unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); |
223 | 223 | ||
224 | __flush_invalidate_dcache_range((unsigned long) dst, len); | 224 | __flush_invalidate_dcache_range((unsigned long) dst, len); |
225 | if ((vma->vm_flags & VM_EXEC) != 0) { | 225 | if ((vma->vm_flags & VM_EXEC) != 0) |
226 | __invalidate_icache_page_alias(temp, phys); | 226 | __invalidate_icache_page_alias(t, phys); |
227 | } | ||
228 | 227 | ||
229 | } else if ((vma->vm_flags & VM_EXEC) != 0) { | 228 | } else if ((vma->vm_flags & VM_EXEC) != 0) { |
230 | __flush_dcache_range((unsigned long)dst,len); | 229 | __flush_dcache_range((unsigned long)dst,len); |
@@ -245,8 +244,8 @@ extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page, | |||
245 | */ | 244 | */ |
246 | 245 | ||
247 | if (alias) { | 246 | if (alias) { |
248 | unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); | 247 | unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); |
249 | __flush_invalidate_dcache_page_alias(temp, phys); | 248 | __flush_invalidate_dcache_page_alias(t, phys); |
250 | } | 249 | } |
251 | 250 | ||
252 | memcpy(dst, src, len); | 251 | memcpy(dst, src, len); |
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index 245b08f7eaf4..4b7bc8db170f 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c | |||
@@ -254,4 +254,3 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) | |||
254 | die("Oops", regs, sig); | 254 | die("Oops", regs, sig); |
255 | do_exit(sig); | 255 | do_exit(sig); |
256 | } | 256 | } |
257 | |||
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index db955179da2d..7a5156ffebb6 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
@@ -75,15 +75,15 @@ int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) | |||
75 | sysmem.nr_banks++; | 75 | sysmem.nr_banks++; |
76 | } | 76 | } |
77 | sysmem.bank[i].end = start; | 77 | sysmem.bank[i].end = start; |
78 | |||
79 | } else if (end < sysmem.bank[i].end) { | ||
80 | sysmem.bank[i].start = end; | ||
81 | |||
78 | } else { | 82 | } else { |
79 | if (end < sysmem.bank[i].end) | 83 | /* remove entry */ |
80 | sysmem.bank[i].start = end; | 84 | sysmem.nr_banks--; |
81 | else { | 85 | sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start; |
82 | /* remove entry */ | 86 | sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end; |
83 | sysmem.nr_banks--; | ||
84 | sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start; | ||
85 | sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end; | ||
86 | } | ||
87 | } | 87 | } |
88 | return -1; | 88 | return -1; |
89 | } | 89 | } |
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S index b048406d8756..d97ed1ba7b0a 100644 --- a/arch/xtensa/mm/misc.S +++ b/arch/xtensa/mm/misc.S | |||
@@ -29,6 +29,7 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | ENTRY(clear_page) | 31 | ENTRY(clear_page) |
32 | |||
32 | entry a1, 16 | 33 | entry a1, 16 |
33 | 34 | ||
34 | movi a3, 0 | 35 | movi a3, 0 |
@@ -45,6 +46,8 @@ ENTRY(clear_page) | |||
45 | 46 | ||
46 | retw | 47 | retw |
47 | 48 | ||
49 | ENDPROC(clear_page) | ||
50 | |||
48 | /* | 51 | /* |
49 | * copy_page and copy_user_page are the same for non-cache-aliased configs. | 52 | * copy_page and copy_user_page are the same for non-cache-aliased configs. |
50 | * | 53 | * |
@@ -53,6 +56,7 @@ ENTRY(clear_page) | |||
53 | */ | 56 | */ |
54 | 57 | ||
55 | ENTRY(copy_page) | 58 | ENTRY(copy_page) |
59 | |||
56 | entry a1, 16 | 60 | entry a1, 16 |
57 | 61 | ||
58 | __loopi a2, a4, PAGE_SIZE, 32 | 62 | __loopi a2, a4, PAGE_SIZE, 32 |
@@ -84,6 +88,8 @@ ENTRY(copy_page) | |||
84 | 88 | ||
85 | retw | 89 | retw |
86 | 90 | ||
91 | ENDPROC(copy_page) | ||
92 | |||
87 | #ifdef CONFIG_MMU | 93 | #ifdef CONFIG_MMU |
88 | /* | 94 | /* |
89 | * If we have to deal with cache aliasing, we use temporary memory mappings | 95 | * If we have to deal with cache aliasing, we use temporary memory mappings |
@@ -109,6 +115,7 @@ ENTRY(__tlbtemp_mapping_start) | |||
109 | */ | 115 | */ |
110 | 116 | ||
111 | ENTRY(clear_user_page) | 117 | ENTRY(clear_user_page) |
118 | |||
112 | entry a1, 32 | 119 | entry a1, 32 |
113 | 120 | ||
114 | /* Mark page dirty and determine alias. */ | 121 | /* Mark page dirty and determine alias. */ |
@@ -164,6 +171,8 @@ ENTRY(clear_user_page) | |||
164 | 171 | ||
165 | retw | 172 | retw |
166 | 173 | ||
174 | ENDPROC(clear_user_page) | ||
175 | |||
167 | /* | 176 | /* |
168 | * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page) | 177 | * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page) |
169 | * a2 a3 a4 a5 | 178 | * a2 a3 a4 a5 |
@@ -171,7 +180,7 @@ ENTRY(clear_user_page) | |||
171 | 180 | ||
172 | ENTRY(copy_user_page) | 181 | ENTRY(copy_user_page) |
173 | 182 | ||
174 | entry a1, 32 | 183 | entry a1, 32 |
175 | 184 | ||
176 | /* Mark page dirty and determine alias for destination. */ | 185 | /* Mark page dirty and determine alias for destination. */ |
177 | 186 | ||
@@ -262,6 +271,8 @@ ENTRY(copy_user_page) | |||
262 | 271 | ||
263 | retw | 272 | retw |
264 | 273 | ||
274 | ENDPROC(copy_user_page) | ||
275 | |||
265 | #endif | 276 | #endif |
266 | 277 | ||
267 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) | 278 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) |
@@ -272,6 +283,7 @@ ENTRY(copy_user_page) | |||
272 | */ | 283 | */ |
273 | 284 | ||
274 | ENTRY(__flush_invalidate_dcache_page_alias) | 285 | ENTRY(__flush_invalidate_dcache_page_alias) |
286 | |||
275 | entry sp, 16 | 287 | entry sp, 16 |
276 | 288 | ||
277 | movi a7, 0 # required for exception handler | 289 | movi a7, 0 # required for exception handler |
@@ -287,6 +299,7 @@ ENTRY(__flush_invalidate_dcache_page_alias) | |||
287 | 299 | ||
288 | retw | 300 | retw |
289 | 301 | ||
302 | ENDPROC(__flush_invalidate_dcache_page_alias) | ||
290 | #endif | 303 | #endif |
291 | 304 | ||
292 | ENTRY(__tlbtemp_mapping_itlb) | 305 | ENTRY(__tlbtemp_mapping_itlb) |
@@ -294,6 +307,7 @@ ENTRY(__tlbtemp_mapping_itlb) | |||
294 | #if (ICACHE_WAY_SIZE > PAGE_SIZE) | 307 | #if (ICACHE_WAY_SIZE > PAGE_SIZE) |
295 | 308 | ||
296 | ENTRY(__invalidate_icache_page_alias) | 309 | ENTRY(__invalidate_icache_page_alias) |
310 | |||
297 | entry sp, 16 | 311 | entry sp, 16 |
298 | 312 | ||
299 | addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE) | 313 | addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE) |
@@ -307,11 +321,14 @@ ENTRY(__invalidate_icache_page_alias) | |||
307 | isync | 321 | isync |
308 | retw | 322 | retw |
309 | 323 | ||
324 | ENDPROC(__invalidate_icache_page_alias) | ||
325 | |||
310 | #endif | 326 | #endif |
311 | 327 | ||
312 | /* End of special treatment in tlb miss exception */ | 328 | /* End of special treatment in tlb miss exception */ |
313 | 329 | ||
314 | ENTRY(__tlbtemp_mapping_end) | 330 | ENTRY(__tlbtemp_mapping_end) |
331 | |||
315 | #endif /* CONFIG_MMU | 332 | #endif /* CONFIG_MMU |
316 | 333 | ||
317 | /* | 334 | /* |
@@ -319,6 +336,7 @@ ENTRY(__tlbtemp_mapping_end) | |||
319 | */ | 336 | */ |
320 | 337 | ||
321 | ENTRY(__invalidate_icache_page) | 338 | ENTRY(__invalidate_icache_page) |
339 | |||
322 | entry sp, 16 | 340 | entry sp, 16 |
323 | 341 | ||
324 | ___invalidate_icache_page a2 a3 | 342 | ___invalidate_icache_page a2 a3 |
@@ -326,11 +344,14 @@ ENTRY(__invalidate_icache_page) | |||
326 | 344 | ||
327 | retw | 345 | retw |
328 | 346 | ||
347 | ENDPROC(__invalidate_icache_page) | ||
348 | |||
329 | /* | 349 | /* |
330 | * void __invalidate_dcache_page(ulong start) | 350 | * void __invalidate_dcache_page(ulong start) |
331 | */ | 351 | */ |
332 | 352 | ||
333 | ENTRY(__invalidate_dcache_page) | 353 | ENTRY(__invalidate_dcache_page) |
354 | |||
334 | entry sp, 16 | 355 | entry sp, 16 |
335 | 356 | ||
336 | ___invalidate_dcache_page a2 a3 | 357 | ___invalidate_dcache_page a2 a3 |
@@ -338,11 +359,14 @@ ENTRY(__invalidate_dcache_page) | |||
338 | 359 | ||
339 | retw | 360 | retw |
340 | 361 | ||
362 | ENDPROC(__invalidate_dcache_page) | ||
363 | |||
341 | /* | 364 | /* |
342 | * void __flush_invalidate_dcache_page(ulong start) | 365 | * void __flush_invalidate_dcache_page(ulong start) |
343 | */ | 366 | */ |
344 | 367 | ||
345 | ENTRY(__flush_invalidate_dcache_page) | 368 | ENTRY(__flush_invalidate_dcache_page) |
369 | |||
346 | entry sp, 16 | 370 | entry sp, 16 |
347 | 371 | ||
348 | ___flush_invalidate_dcache_page a2 a3 | 372 | ___flush_invalidate_dcache_page a2 a3 |
@@ -350,11 +374,14 @@ ENTRY(__flush_invalidate_dcache_page) | |||
350 | dsync | 374 | dsync |
351 | retw | 375 | retw |
352 | 376 | ||
377 | ENDPROC(__flush_invalidate_dcache_page) | ||
378 | |||
353 | /* | 379 | /* |
354 | * void __flush_dcache_page(ulong start) | 380 | * void __flush_dcache_page(ulong start) |
355 | */ | 381 | */ |
356 | 382 | ||
357 | ENTRY(__flush_dcache_page) | 383 | ENTRY(__flush_dcache_page) |
384 | |||
358 | entry sp, 16 | 385 | entry sp, 16 |
359 | 386 | ||
360 | ___flush_dcache_page a2 a3 | 387 | ___flush_dcache_page a2 a3 |
@@ -362,11 +389,14 @@ ENTRY(__flush_dcache_page) | |||
362 | dsync | 389 | dsync |
363 | retw | 390 | retw |
364 | 391 | ||
392 | ENDPROC(__flush_dcache_page) | ||
393 | |||
365 | /* | 394 | /* |
366 | * void __invalidate_icache_range(ulong start, ulong size) | 395 | * void __invalidate_icache_range(ulong start, ulong size) |
367 | */ | 396 | */ |
368 | 397 | ||
369 | ENTRY(__invalidate_icache_range) | 398 | ENTRY(__invalidate_icache_range) |
399 | |||
370 | entry sp, 16 | 400 | entry sp, 16 |
371 | 401 | ||
372 | ___invalidate_icache_range a2 a3 a4 | 402 | ___invalidate_icache_range a2 a3 a4 |
@@ -374,11 +404,14 @@ ENTRY(__invalidate_icache_range) | |||
374 | 404 | ||
375 | retw | 405 | retw |
376 | 406 | ||
407 | ENDPROC(__invalidate_icache_range) | ||
408 | |||
377 | /* | 409 | /* |
378 | * void __flush_invalidate_dcache_range(ulong start, ulong size) | 410 | * void __flush_invalidate_dcache_range(ulong start, ulong size) |
379 | */ | 411 | */ |
380 | 412 | ||
381 | ENTRY(__flush_invalidate_dcache_range) | 413 | ENTRY(__flush_invalidate_dcache_range) |
414 | |||
382 | entry sp, 16 | 415 | entry sp, 16 |
383 | 416 | ||
384 | ___flush_invalidate_dcache_range a2 a3 a4 | 417 | ___flush_invalidate_dcache_range a2 a3 a4 |
@@ -386,11 +419,14 @@ ENTRY(__flush_invalidate_dcache_range) | |||
386 | 419 | ||
387 | retw | 420 | retw |
388 | 421 | ||
422 | ENDPROC(__flush_invalidate_dcache_range) | ||
423 | |||
389 | /* | 424 | /* |
390 | * void _flush_dcache_range(ulong start, ulong size) | 425 | * void _flush_dcache_range(ulong start, ulong size) |
391 | */ | 426 | */ |
392 | 427 | ||
393 | ENTRY(__flush_dcache_range) | 428 | ENTRY(__flush_dcache_range) |
429 | |||
394 | entry sp, 16 | 430 | entry sp, 16 |
395 | 431 | ||
396 | ___flush_dcache_range a2 a3 a4 | 432 | ___flush_dcache_range a2 a3 a4 |
@@ -398,22 +434,28 @@ ENTRY(__flush_dcache_range) | |||
398 | 434 | ||
399 | retw | 435 | retw |
400 | 436 | ||
437 | ENDPROC(__flush_dcache_range) | ||
438 | |||
401 | /* | 439 | /* |
402 | * void _invalidate_dcache_range(ulong start, ulong size) | 440 | * void _invalidate_dcache_range(ulong start, ulong size) |
403 | */ | 441 | */ |
404 | 442 | ||
405 | ENTRY(__invalidate_dcache_range) | 443 | ENTRY(__invalidate_dcache_range) |
444 | |||
406 | entry sp, 16 | 445 | entry sp, 16 |
407 | 446 | ||
408 | ___invalidate_dcache_range a2 a3 a4 | 447 | ___invalidate_dcache_range a2 a3 a4 |
409 | 448 | ||
410 | retw | 449 | retw |
411 | 450 | ||
451 | ENDPROC(__invalidate_dcache_range) | ||
452 | |||
412 | /* | 453 | /* |
413 | * void _invalidate_icache_all(void) | 454 | * void _invalidate_icache_all(void) |
414 | */ | 455 | */ |
415 | 456 | ||
416 | ENTRY(__invalidate_icache_all) | 457 | ENTRY(__invalidate_icache_all) |
458 | |||
417 | entry sp, 16 | 459 | entry sp, 16 |
418 | 460 | ||
419 | ___invalidate_icache_all a2 a3 | 461 | ___invalidate_icache_all a2 a3 |
@@ -421,11 +463,14 @@ ENTRY(__invalidate_icache_all) | |||
421 | 463 | ||
422 | retw | 464 | retw |
423 | 465 | ||
466 | ENDPROC(__invalidate_icache_all) | ||
467 | |||
424 | /* | 468 | /* |
425 | * void _flush_invalidate_dcache_all(void) | 469 | * void _flush_invalidate_dcache_all(void) |
426 | */ | 470 | */ |
427 | 471 | ||
428 | ENTRY(__flush_invalidate_dcache_all) | 472 | ENTRY(__flush_invalidate_dcache_all) |
473 | |||
429 | entry sp, 16 | 474 | entry sp, 16 |
430 | 475 | ||
431 | ___flush_invalidate_dcache_all a2 a3 | 476 | ___flush_invalidate_dcache_all a2 a3 |
@@ -433,11 +478,14 @@ ENTRY(__flush_invalidate_dcache_all) | |||
433 | 478 | ||
434 | retw | 479 | retw |
435 | 480 | ||
481 | ENDPROC(__flush_invalidate_dcache_all) | ||
482 | |||
436 | /* | 483 | /* |
437 | * void _invalidate_dcache_all(void) | 484 | * void _invalidate_dcache_all(void) |
438 | */ | 485 | */ |
439 | 486 | ||
440 | ENTRY(__invalidate_dcache_all) | 487 | ENTRY(__invalidate_dcache_all) |
488 | |||
441 | entry sp, 16 | 489 | entry sp, 16 |
442 | 490 | ||
443 | ___invalidate_dcache_all a2 a3 | 491 | ___invalidate_dcache_all a2 a3 |
@@ -445,3 +493,4 @@ ENTRY(__invalidate_dcache_all) | |||
445 | 493 | ||
446 | retw | 494 | retw |
447 | 495 | ||
496 | ENDPROC(__invalidate_dcache_all) | ||
diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index ca81654f3ec2..0f77f9d3bb8b 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c | |||
@@ -37,7 +37,7 @@ void __init init_mmu(void) | |||
37 | 37 | ||
38 | /* Set rasid register to a known value. */ | 38 | /* Set rasid register to a known value. */ |
39 | 39 | ||
40 | set_rasid_register(ASID_USER_FIRST); | 40 | set_rasid_register(ASID_INSERT(ASID_USER_FIRST)); |
41 | 41 | ||
42 | /* Set PTEVADDR special register to the start of the page | 42 | /* Set PTEVADDR special register to the start of the page |
43 | * table, which is in kernel mappable space (ie. not | 43 | * table, which is in kernel mappable space (ie. not |
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index e2700b21395b..5411aa67c68e 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c | |||
@@ -63,7 +63,7 @@ void flush_tlb_all (void) | |||
63 | void flush_tlb_mm(struct mm_struct *mm) | 63 | void flush_tlb_mm(struct mm_struct *mm) |
64 | { | 64 | { |
65 | if (mm == current->active_mm) { | 65 | if (mm == current->active_mm) { |
66 | int flags; | 66 | unsigned long flags; |
67 | local_save_flags(flags); | 67 | local_save_flags(flags); |
68 | __get_new_mmu_context(mm); | 68 | __get_new_mmu_context(mm); |
69 | __load_mmu_context(mm); | 69 | __load_mmu_context(mm); |
@@ -82,7 +82,7 @@ void flush_tlb_mm(struct mm_struct *mm) | |||
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | void flush_tlb_range (struct vm_area_struct *vma, | 84 | void flush_tlb_range (struct vm_area_struct *vma, |
85 | unsigned long start, unsigned long end) | 85 | unsigned long start, unsigned long end) |
86 | { | 86 | { |
87 | struct mm_struct *mm = vma->vm_mm; | 87 | struct mm_struct *mm = vma->vm_mm; |
88 | unsigned long flags; | 88 | unsigned long flags; |
@@ -100,7 +100,7 @@ void flush_tlb_range (struct vm_area_struct *vma, | |||
100 | int oldpid = get_rasid_register(); | 100 | int oldpid = get_rasid_register(); |
101 | set_rasid_register (ASID_INSERT(mm->context)); | 101 | set_rasid_register (ASID_INSERT(mm->context)); |
102 | start &= PAGE_MASK; | 102 | start &= PAGE_MASK; |
103 | if (vma->vm_flags & VM_EXEC) | 103 | if (vma->vm_flags & VM_EXEC) |
104 | while(start < end) { | 104 | while(start < end) { |
105 | invalidate_itlb_mapping(start); | 105 | invalidate_itlb_mapping(start); |
106 | invalidate_dtlb_mapping(start); | 106 | invalidate_dtlb_mapping(start); |
@@ -130,7 +130,7 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) | |||
130 | 130 | ||
131 | local_save_flags(flags); | 131 | local_save_flags(flags); |
132 | 132 | ||
133 | oldpid = get_rasid_register(); | 133 | oldpid = get_rasid_register(); |
134 | 134 | ||
135 | if (vma->vm_flags & VM_EXEC) | 135 | if (vma->vm_flags & VM_EXEC) |
136 | invalidate_itlb_mapping(page); | 136 | invalidate_itlb_mapping(page); |
@@ -140,4 +140,3 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) | |||
140 | 140 | ||
141 | local_irq_restore(flags); | 141 | local_irq_restore(flags); |
142 | } | 142 | } |
143 | |||
diff --git a/arch/xtensa/platforms/iss/include/platform/serial.h b/arch/xtensa/platforms/iss/include/platform/serial.h index e69de29bb2d1..16aec542d435 100644 --- a/arch/xtensa/platforms/iss/include/platform/serial.h +++ b/arch/xtensa/platforms/iss/include/platform/serial.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2012 Tensilica Inc. | ||
7 | */ | ||
8 | |||
9 | #ifndef __ASM_XTENSA_ISS_SERIAL_H | ||
10 | #define __ASM_XTENSA_ISS_SERIAL_H | ||
11 | |||
12 | /* Have no meaning on ISS, but needed for 8250_early.c */ | ||
13 | #define BASE_BAUD 0 | ||
14 | |||
15 | #endif /* __ASM_XTENSA_ISS_SERIAL_H */ | ||
diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h index bd78192e2fc9..b5a4edf02d76 100644 --- a/arch/xtensa/platforms/iss/include/platform/simcall.h +++ b/arch/xtensa/platforms/iss/include/platform/simcall.h | |||
@@ -74,13 +74,12 @@ static inline int __simc(int a, int b, int c, int d, int e, int f) | |||
74 | "mov %1, a3\n" | 74 | "mov %1, a3\n" |
75 | : "=a" (ret), "=a" (errno), "+r"(a1), "+r"(b1) | 75 | : "=a" (ret), "=a" (errno), "+r"(a1), "+r"(b1) |
76 | : "r"(c1), "r"(d1), "r"(e1), "r"(f1) | 76 | : "r"(c1), "r"(d1), "r"(e1), "r"(f1) |
77 | : ); | 77 | : "memory"); |
78 | return ret; | 78 | return ret; |
79 | } | 79 | } |
80 | 80 | ||
81 | static inline int simc_open(const char *file, int flags, int mode) | 81 | static inline int simc_open(const char *file, int flags, int mode) |
82 | { | 82 | { |
83 | wmb(); | ||
84 | return __simc(SYS_open, (int) file, flags, mode, 0, 0); | 83 | return __simc(SYS_open, (int) file, flags, mode, 0, 0); |
85 | } | 84 | } |
86 | 85 | ||
@@ -91,19 +90,16 @@ static inline int simc_close(int fd) | |||
91 | 90 | ||
92 | static inline int simc_ioctl(int fd, int request, void *arg) | 91 | static inline int simc_ioctl(int fd, int request, void *arg) |
93 | { | 92 | { |
94 | wmb(); | ||
95 | return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0); | 93 | return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0); |
96 | } | 94 | } |
97 | 95 | ||
98 | static inline int simc_read(int fd, void *buf, size_t count) | 96 | static inline int simc_read(int fd, void *buf, size_t count) |
99 | { | 97 | { |
100 | rmb(); | ||
101 | return __simc(SYS_read, fd, (int) buf, count, 0, 0); | 98 | return __simc(SYS_read, fd, (int) buf, count, 0, 0); |
102 | } | 99 | } |
103 | 100 | ||
104 | static inline int simc_write(int fd, const void *buf, size_t count) | 101 | static inline int simc_write(int fd, const void *buf, size_t count) |
105 | { | 102 | { |
106 | wmb(); | ||
107 | return __simc(SYS_write, fd, (int) buf, count, 0, 0); | 103 | return __simc(SYS_write, fd, (int) buf, count, 0, 0); |
108 | } | 104 | } |
109 | 105 | ||
@@ -111,7 +107,6 @@ static inline int simc_poll(int fd) | |||
111 | { | 107 | { |
112 | struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; | 108 | struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; |
113 | 109 | ||
114 | wmb(); | ||
115 | return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv, | 110 | return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv, |
116 | 0, 0); | 111 | 0, 0); |
117 | } | 112 | } |
diff --git a/arch/xtensa/platforms/xtfpga/Makefile b/arch/xtensa/platforms/xtfpga/Makefile new file mode 100644 index 000000000000..b9ae206340cd --- /dev/null +++ b/arch/xtensa/platforms/xtfpga/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # Makefile for the Tensilica xtavnet Emulation Board | ||
2 | # | ||
3 | # Note! Dependencies are done automagically by 'make dep', which also | ||
4 | # removes any old dependencies. DON'T put your own dependencies here | ||
5 | # unless it's something special (ie not a .c file). | ||
6 | # | ||
7 | # Note 2! The CFLAGS definitions are in the main makefile... | ||
8 | |||
9 | obj-y = setup.o lcd.o | ||
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h new file mode 100644 index 000000000000..4416773cbde5 --- /dev/null +++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * arch/xtensa/platform/xtavnet/include/platform/hardware.h | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2006 Tensilica Inc. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This file contains the hardware configuration of the XTAVNET boards. | ||
13 | */ | ||
14 | |||
15 | #ifndef __XTENSA_XTAVNET_HARDWARE_H | ||
16 | #define __XTENSA_XTAVNET_HARDWARE_H | ||
17 | |||
18 | /* By default NO_IRQ is defined to 0 in Linux, but we use the | ||
19 | interrupt 0 for UART... */ | ||
20 | #define NO_IRQ -1 | ||
21 | |||
22 | /* Memory configuration. */ | ||
23 | |||
24 | #define PLATFORM_DEFAULT_MEM_START 0x00000000 | ||
25 | #define PLATFORM_DEFAULT_MEM_SIZE 0x04000000 | ||
26 | |||
27 | /* Interrupt configuration. */ | ||
28 | |||
29 | #define PLATFORM_NR_IRQS 10 | ||
30 | |||
31 | /* Default assignment of LX60 devices to external interrupts. */ | ||
32 | |||
33 | #ifdef CONFIG_ARCH_HAS_SMP | ||
34 | #define DUART16552_INTNUM XCHAL_EXTINT3_NUM | ||
35 | #define OETH_IRQ XCHAL_EXTINT4_NUM | ||
36 | #else | ||
37 | #define DUART16552_INTNUM XCHAL_EXTINT0_NUM | ||
38 | #define OETH_IRQ XCHAL_EXTINT1_NUM | ||
39 | #endif | ||
40 | |||
41 | /* | ||
42 | * Device addresses and parameters. | ||
43 | */ | ||
44 | |||
45 | /* UART */ | ||
46 | #define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020) | ||
47 | /* LCD instruction and data addresses. */ | ||
48 | #define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000)) | ||
49 | #define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004)) | ||
50 | |||
51 | /* Misc. */ | ||
52 | #define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000) | ||
53 | /* Clock frequency in Hz (read-only): */ | ||
54 | #define XTFPGA_CLKFRQ_VADDR (XTFPGA_FPGAREGS_VADDR + 0x04) | ||
55 | /* Setting of 8 DIP switches: */ | ||
56 | #define DIP_SWITCHES_VADDR (XTFPGA_FPGAREGS_VADDR + 0x0C) | ||
57 | /* Software reset (write 0xdead): */ | ||
58 | #define XTFPGA_SWRST_VADDR (XTFPGA_FPGAREGS_VADDR + 0x10) | ||
59 | |||
60 | /* OpenCores Ethernet controller: */ | ||
61 | /* regs + RX/TX descriptors */ | ||
62 | #define OETH_REGS_PADDR (XCHAL_KIO_PADDR + 0x0D030000) | ||
63 | #define OETH_REGS_SIZE 0x1000 | ||
64 | #define OETH_SRAMBUFF_PADDR (XCHAL_KIO_PADDR + 0x0D800000) | ||
65 | |||
66 | /* 5*rx buffs + 5*tx buffs */ | ||
67 | #define OETH_SRAMBUFF_SIZE (5 * 0x600 + 5 * 0x600) | ||
68 | |||
69 | #endif /* __XTENSA_XTAVNET_HARDWARE_H */ | ||
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h new file mode 100644 index 000000000000..0e435645af5a --- /dev/null +++ b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * arch/xtensa/platform/xtavnet/include/platform/lcd.h | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2001, 2006 Tensilica Inc. | ||
9 | */ | ||
10 | |||
11 | #ifndef __XTENSA_XTAVNET_LCD_H | ||
12 | #define __XTENSA_XTAVNET_LCD_H | ||
13 | |||
14 | /* Display string STR at position POS on the LCD. */ | ||
15 | void lcd_disp_at_pos(char *str, unsigned char pos); | ||
16 | |||
17 | /* Shift the contents of the LCD display left or right. */ | ||
18 | void lcd_shiftleft(void); | ||
19 | void lcd_shiftright(void); | ||
20 | #endif | ||
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/serial.h b/arch/xtensa/platforms/xtfpga/include/platform/serial.h new file mode 100644 index 000000000000..14d8f7beebfd --- /dev/null +++ b/arch/xtensa/platforms/xtfpga/include/platform/serial.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * arch/xtensa/platform/xtavnet/include/platform/serial.h | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2001, 2006 Tensilica Inc. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_XTENSA_XTAVNET_SERIAL_H | ||
12 | #define __ASM_XTENSA_XTAVNET_SERIAL_H | ||
13 | |||
14 | #include <platform/hardware.h> | ||
15 | |||
16 | #define BASE_BAUD (*(long *)XTFPGA_CLKFRQ_VADDR / 16) | ||
17 | |||
18 | #endif /* __ASM_XTENSA_XTAVNET_SERIAL_H */ | ||
diff --git a/arch/xtensa/platforms/xtfpga/lcd.c b/arch/xtensa/platforms/xtfpga/lcd.c new file mode 100644 index 000000000000..2872301598df --- /dev/null +++ b/arch/xtensa/platforms/xtfpga/lcd.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Driver for the LCD display on the Tensilica LX60 Board. | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2001, 2006 Tensilica Inc. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * | ||
13 | * FIXME: this code is from the examples from the LX60 user guide. | ||
14 | * | ||
15 | * The lcd_pause function does busy waiting, which is probably not | ||
16 | * great. Maybe the code could be changed to use kernel timers, or | ||
17 | * change the hardware to not need to wait. | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <platform/hardware.h> | ||
24 | #include <platform/lcd.h> | ||
25 | #include <linux/delay.h> | ||
26 | |||
27 | #define LCD_PAUSE_ITERATIONS 4000 | ||
28 | #define LCD_CLEAR 0x1 | ||
29 | #define LCD_DISPLAY_ON 0xc | ||
30 | |||
31 | /* 8bit and 2 lines display */ | ||
32 | #define LCD_DISPLAY_MODE8BIT 0x38 | ||
33 | #define LCD_DISPLAY_POS 0x80 | ||
34 | #define LCD_SHIFT_LEFT 0x18 | ||
35 | #define LCD_SHIFT_RIGHT 0x1c | ||
36 | |||
37 | static int __init lcd_init(void) | ||
38 | { | ||
39 | *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; | ||
40 | mdelay(5); | ||
41 | *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; | ||
42 | udelay(200); | ||
43 | *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; | ||
44 | udelay(50); | ||
45 | *LCD_INSTR_ADDR = LCD_DISPLAY_ON; | ||
46 | udelay(50); | ||
47 | *LCD_INSTR_ADDR = LCD_CLEAR; | ||
48 | mdelay(10); | ||
49 | lcd_disp_at_pos("XTENSA LINUX", 0); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | void lcd_disp_at_pos(char *str, unsigned char pos) | ||
54 | { | ||
55 | *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos; | ||
56 | udelay(100); | ||
57 | while (*str != 0) { | ||
58 | *LCD_DATA_ADDR = *str; | ||
59 | udelay(200); | ||
60 | str++; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void lcd_shiftleft(void) | ||
65 | { | ||
66 | *LCD_INSTR_ADDR = LCD_SHIFT_LEFT; | ||
67 | udelay(50); | ||
68 | } | ||
69 | |||
70 | void lcd_shiftright(void) | ||
71 | { | ||
72 | *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT; | ||
73 | udelay(50); | ||
74 | } | ||
75 | |||
76 | arch_initcall(lcd_init); | ||
diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c new file mode 100644 index 000000000000..4b9951a4569d --- /dev/null +++ b/arch/xtensa/platforms/xtfpga/setup.c | |||
@@ -0,0 +1,301 @@ | |||
1 | /* | ||
2 | * | ||
3 | * arch/xtensa/platform/xtavnet/setup.c | ||
4 | * | ||
5 | * ... | ||
6 | * | ||
7 | * Authors: Chris Zankel <chris@zankel.net> | ||
8 | * Joe Taylor <joe@tensilica.com> | ||
9 | * | ||
10 | * Copyright 2001 - 2006 Tensilica Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/reboot.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/console.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/of.h> | ||
29 | |||
30 | #include <asm/timex.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <asm/platform.h> | ||
33 | #include <asm/bootparam.h> | ||
34 | #include <platform/lcd.h> | ||
35 | #include <platform/hardware.h> | ||
36 | |||
37 | void platform_halt(void) | ||
38 | { | ||
39 | lcd_disp_at_pos(" HALT ", 0); | ||
40 | local_irq_disable(); | ||
41 | while (1) | ||
42 | cpu_relax(); | ||
43 | } | ||
44 | |||
45 | void platform_power_off(void) | ||
46 | { | ||
47 | lcd_disp_at_pos("POWEROFF", 0); | ||
48 | local_irq_disable(); | ||
49 | while (1) | ||
50 | cpu_relax(); | ||
51 | } | ||
52 | |||
53 | void platform_restart(void) | ||
54 | { | ||
55 | /* Flush and reset the mmu, simulate a processor reset, and | ||
56 | * jump to the reset vector. */ | ||
57 | |||
58 | |||
59 | __asm__ __volatile__ ("movi a2, 15\n\t" | ||
60 | "wsr a2, icountlevel\n\t" | ||
61 | "movi a2, 0\n\t" | ||
62 | "wsr a2, icount\n\t" | ||
63 | "wsr a2, ibreakenable\n\t" | ||
64 | "wsr a2, lcount\n\t" | ||
65 | "movi a2, 0x1f\n\t" | ||
66 | "wsr a2, ps\n\t" | ||
67 | "isync\n\t" | ||
68 | "jx %0\n\t" | ||
69 | : | ||
70 | : "a" (XCHAL_RESET_VECTOR_VADDR) | ||
71 | : "a2" | ||
72 | ); | ||
73 | |||
74 | /* control never gets here */ | ||
75 | } | ||
76 | |||
77 | void __init platform_setup(char **cmdline) | ||
78 | { | ||
79 | } | ||
80 | |||
81 | #ifdef CONFIG_OF | ||
82 | |||
83 | static void __init update_clock_frequency(struct device_node *node) | ||
84 | { | ||
85 | struct property *newfreq; | ||
86 | u32 freq; | ||
87 | |||
88 | if (!of_property_read_u32(node, "clock-frequency", &freq) && freq != 0) | ||
89 | return; | ||
90 | |||
91 | newfreq = kzalloc(sizeof(*newfreq) + sizeof(u32), GFP_KERNEL); | ||
92 | if (!newfreq) | ||
93 | return; | ||
94 | newfreq->value = newfreq + 1; | ||
95 | newfreq->length = sizeof(freq); | ||
96 | newfreq->name = kstrdup("clock-frequency", GFP_KERNEL); | ||
97 | if (!newfreq->name) { | ||
98 | kfree(newfreq); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | *(u32 *)newfreq->value = cpu_to_be32(*(u32 *)XTFPGA_CLKFRQ_VADDR); | ||
103 | prom_update_property(node, newfreq); | ||
104 | } | ||
105 | |||
106 | #define MAC_LEN 6 | ||
107 | static void __init update_local_mac(struct device_node *node) | ||
108 | { | ||
109 | struct property *newmac; | ||
110 | const u8* macaddr; | ||
111 | int prop_len; | ||
112 | |||
113 | macaddr = of_get_property(node, "local-mac-address", &prop_len); | ||
114 | if (macaddr == NULL || prop_len != MAC_LEN) | ||
115 | return; | ||
116 | |||
117 | newmac = kzalloc(sizeof(*newmac) + MAC_LEN, GFP_KERNEL); | ||
118 | if (newmac == NULL) | ||
119 | return; | ||
120 | |||
121 | newmac->value = newmac + 1; | ||
122 | newmac->length = MAC_LEN; | ||
123 | newmac->name = kstrdup("local-mac-address", GFP_KERNEL); | ||
124 | if (newmac->name == NULL) { | ||
125 | kfree(newmac); | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | memcpy(newmac->value, macaddr, MAC_LEN); | ||
130 | ((u8*)newmac->value)[5] = (*(u32*)DIP_SWITCHES_VADDR) & 0x3f; | ||
131 | prom_update_property(node, newmac); | ||
132 | } | ||
133 | |||
134 | static int __init machine_setup(void) | ||
135 | { | ||
136 | struct device_node *serial; | ||
137 | struct device_node *eth = NULL; | ||
138 | |||
139 | for_each_compatible_node(serial, NULL, "ns16550a") | ||
140 | update_clock_frequency(serial); | ||
141 | |||
142 | if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc"))) | ||
143 | update_local_mac(eth); | ||
144 | return 0; | ||
145 | } | ||
146 | arch_initcall(machine_setup); | ||
147 | |||
148 | #endif | ||
149 | |||
150 | /* early initialization */ | ||
151 | |||
152 | void __init platform_init(bp_tag_t *first) | ||
153 | { | ||
154 | } | ||
155 | |||
156 | /* Heartbeat. */ | ||
157 | |||
158 | void platform_heartbeat(void) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | ||
163 | |||
164 | void platform_calibrate_ccount(void) | ||
165 | { | ||
166 | long clk_freq = 0; | ||
167 | #ifdef CONFIG_OF | ||
168 | struct device_node *cpu = | ||
169 | of_find_compatible_node(NULL, NULL, "xtensa,cpu"); | ||
170 | if (cpu) { | ||
171 | u32 freq; | ||
172 | update_clock_frequency(cpu); | ||
173 | if (!of_property_read_u32(cpu, "clock-frequency", &freq)) | ||
174 | clk_freq = freq; | ||
175 | } | ||
176 | #endif | ||
177 | if (!clk_freq) | ||
178 | clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR; | ||
179 | |||
180 | ccount_per_jiffy = clk_freq / HZ; | ||
181 | nsec_per_ccount = 1000000000UL / clk_freq; | ||
182 | } | ||
183 | |||
184 | #endif | ||
185 | |||
186 | #ifndef CONFIG_OF | ||
187 | |||
188 | #include <linux/serial_8250.h> | ||
189 | #include <linux/if.h> | ||
190 | #include <net/ethoc.h> | ||
191 | |||
192 | /*---------------------------------------------------------------------------- | ||
193 | * Ethernet -- OpenCores Ethernet MAC (ethoc driver) | ||
194 | */ | ||
195 | |||
196 | static struct resource ethoc_res[] __initdata = { | ||
197 | [0] = { /* register space */ | ||
198 | .start = OETH_REGS_PADDR, | ||
199 | .end = OETH_REGS_PADDR + OETH_REGS_SIZE - 1, | ||
200 | .flags = IORESOURCE_MEM, | ||
201 | }, | ||
202 | [1] = { /* buffer space */ | ||
203 | .start = OETH_SRAMBUFF_PADDR, | ||
204 | .end = OETH_SRAMBUFF_PADDR + OETH_SRAMBUFF_SIZE - 1, | ||
205 | .flags = IORESOURCE_MEM, | ||
206 | }, | ||
207 | [2] = { /* IRQ number */ | ||
208 | .start = OETH_IRQ, | ||
209 | .end = OETH_IRQ, | ||
210 | .flags = IORESOURCE_IRQ, | ||
211 | }, | ||
212 | }; | ||
213 | |||
214 | static struct ethoc_platform_data ethoc_pdata __initdata = { | ||
215 | /* | ||
216 | * The MAC address for these boards is 00:50:c2:13:6f:xx. | ||
217 | * The last byte (here as zero) is read from the DIP switches on the | ||
218 | * board. | ||
219 | */ | ||
220 | .hwaddr = { 0x00, 0x50, 0xc2, 0x13, 0x6f, 0 }, | ||
221 | .phy_id = -1, | ||
222 | }; | ||
223 | |||
224 | static struct platform_device ethoc_device __initdata = { | ||
225 | .name = "ethoc", | ||
226 | .id = -1, | ||
227 | .num_resources = ARRAY_SIZE(ethoc_res), | ||
228 | .resource = ethoc_res, | ||
229 | .dev = { | ||
230 | .platform_data = ðoc_pdata, | ||
231 | }, | ||
232 | }; | ||
233 | |||
234 | /*---------------------------------------------------------------------------- | ||
235 | * UART | ||
236 | */ | ||
237 | |||
238 | static struct resource serial_resource __initdata = { | ||
239 | .start = DUART16552_PADDR, | ||
240 | .end = DUART16552_PADDR + 0x1f, | ||
241 | .flags = IORESOURCE_MEM, | ||
242 | }; | ||
243 | |||
244 | static struct plat_serial8250_port serial_platform_data[] __initdata = { | ||
245 | [0] = { | ||
246 | .mapbase = DUART16552_PADDR, | ||
247 | .irq = DUART16552_INTNUM, | ||
248 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | | ||
249 | UPF_IOREMAP, | ||
250 | .iotype = UPIO_MEM32, | ||
251 | .regshift = 2, | ||
252 | .uartclk = 0, /* set in xtavnet_init() */ | ||
253 | }, | ||
254 | { }, | ||
255 | }; | ||
256 | |||
257 | static struct platform_device xtavnet_uart __initdata = { | ||
258 | .name = "serial8250", | ||
259 | .id = PLAT8250_DEV_PLATFORM, | ||
260 | .dev = { | ||
261 | .platform_data = serial_platform_data, | ||
262 | }, | ||
263 | .num_resources = 1, | ||
264 | .resource = &serial_resource, | ||
265 | }; | ||
266 | |||
267 | /* platform devices */ | ||
268 | static struct platform_device *platform_devices[] __initdata = { | ||
269 | ðoc_device, | ||
270 | &xtavnet_uart, | ||
271 | }; | ||
272 | |||
273 | |||
274 | static int __init xtavnet_init(void) | ||
275 | { | ||
276 | /* Ethernet MAC address. */ | ||
277 | ethoc_pdata.hwaddr[5] = *(u32 *)DIP_SWITCHES_VADDR; | ||
278 | |||
279 | /* Clock rate varies among FPGA bitstreams; board specific FPGA register | ||
280 | * reports the actual clock rate. | ||
281 | */ | ||
282 | serial_platform_data[0].uartclk = *(long *)XTFPGA_CLKFRQ_VADDR; | ||
283 | |||
284 | |||
285 | /* register platform devices */ | ||
286 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | ||
287 | |||
288 | /* ETHOC driver is a bit quiet; at least display Ethernet MAC, so user | ||
289 | * knows whether they set it correctly on the DIP switches. | ||
290 | */ | ||
291 | pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * Register to be done during do_initcalls(). | ||
298 | */ | ||
299 | arch_initcall(xtavnet_init); | ||
300 | |||
301 | #endif /* CONFIG_OF */ | ||
diff --git a/arch/xtensa/variants/s6000/gpio.c b/arch/xtensa/variants/s6000/gpio.c index b89541ba39ab..da9e85c13b08 100644 --- a/arch/xtensa/variants/s6000/gpio.c +++ b/arch/xtensa/variants/s6000/gpio.c | |||
@@ -164,7 +164,7 @@ static void demux_irqs(unsigned int irq, struct irq_desc *desc) | |||
164 | int cirq; | 164 | int cirq; |
165 | 165 | ||
166 | chip->irq_mask(&desc->irq_data); | 166 | chip->irq_mask(&desc->irq_data); |
167 | chip->irq_ack(&desc->irq_data)); | 167 | chip->irq_ack(&desc->irq_data); |
168 | pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask; | 168 | pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask; |
169 | cirq = IRQ_BASE - 1; | 169 | cirq = IRQ_BASE - 1; |
170 | while (pending) { | 170 | while (pending) { |
@@ -173,7 +173,7 @@ static void demux_irqs(unsigned int irq, struct irq_desc *desc) | |||
173 | pending >>= n; | 173 | pending >>= n; |
174 | generic_handle_irq(cirq); | 174 | generic_handle_irq(cirq); |
175 | } | 175 | } |
176 | chip->irq_unmask(&desc->irq_data)); | 176 | chip->irq_unmask(&desc->irq_data); |
177 | } | 177 | } |
178 | 178 | ||
179 | extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS]; | 179 | extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS]; |
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index e162999bf916..c62c788b3289 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -13,12 +13,13 @@ | |||
13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
14 | #include <linux/bcma/bcma.h> | 14 | #include <linux/bcma/bcma.h> |
15 | 15 | ||
16 | static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) | 16 | u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) |
17 | { | 17 | { |
18 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); | 18 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); |
19 | bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); | 19 | bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); |
20 | return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); | 20 | return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); |
21 | } | 21 | } |
22 | EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); | ||
22 | 23 | ||
23 | void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) | 24 | void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) |
24 | { | 25 | { |
diff --git a/drivers/char/random.c b/drivers/char/random.c index b86eae9b77df..85e81ec1451e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -399,7 +399,6 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); | |||
399 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); | 399 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); |
400 | static struct fasync_struct *fasync; | 400 | static struct fasync_struct *fasync; |
401 | 401 | ||
402 | #if 0 | ||
403 | static bool debug; | 402 | static bool debug; |
404 | module_param(debug, bool, 0644); | 403 | module_param(debug, bool, 0644); |
405 | #define DEBUG_ENT(fmt, arg...) do { \ | 404 | #define DEBUG_ENT(fmt, arg...) do { \ |
@@ -410,9 +409,6 @@ module_param(debug, bool, 0644); | |||
410 | blocking_pool.entropy_count,\ | 409 | blocking_pool.entropy_count,\ |
411 | nonblocking_pool.entropy_count,\ | 410 | nonblocking_pool.entropy_count,\ |
412 | ## arg); } while (0) | 411 | ## arg); } while (0) |
413 | #else | ||
414 | #define DEBUG_ENT(fmt, arg...) do {} while (0) | ||
415 | #endif | ||
416 | 412 | ||
417 | /********************************************************************** | 413 | /********************************************************************** |
418 | * | 414 | * |
@@ -437,6 +433,7 @@ struct entropy_store { | |||
437 | int entropy_count; | 433 | int entropy_count; |
438 | int entropy_total; | 434 | int entropy_total; |
439 | unsigned int initialized:1; | 435 | unsigned int initialized:1; |
436 | bool last_data_init; | ||
440 | __u8 last_data[EXTRACT_SIZE]; | 437 | __u8 last_data[EXTRACT_SIZE]; |
441 | }; | 438 | }; |
442 | 439 | ||
@@ -829,7 +826,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) | |||
829 | bytes = min_t(int, bytes, sizeof(tmp)); | 826 | bytes = min_t(int, bytes, sizeof(tmp)); |
830 | 827 | ||
831 | DEBUG_ENT("going to reseed %s with %d bits " | 828 | DEBUG_ENT("going to reseed %s with %d bits " |
832 | "(%d of %d requested)\n", | 829 | "(%zu of %d requested)\n", |
833 | r->name, bytes * 8, nbytes * 8, r->entropy_count); | 830 | r->name, bytes * 8, nbytes * 8, r->entropy_count); |
834 | 831 | ||
835 | bytes = extract_entropy(r->pull, tmp, bytes, | 832 | bytes = extract_entropy(r->pull, tmp, bytes, |
@@ -860,7 +857,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
860 | spin_lock_irqsave(&r->lock, flags); | 857 | spin_lock_irqsave(&r->lock, flags); |
861 | 858 | ||
862 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); | 859 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); |
863 | DEBUG_ENT("trying to extract %d bits from %s\n", | 860 | DEBUG_ENT("trying to extract %zu bits from %s\n", |
864 | nbytes * 8, r->name); | 861 | nbytes * 8, r->name); |
865 | 862 | ||
866 | /* Can we pull enough? */ | 863 | /* Can we pull enough? */ |
@@ -882,7 +879,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
882 | } | 879 | } |
883 | } | 880 | } |
884 | 881 | ||
885 | DEBUG_ENT("debiting %d entropy credits from %s%s\n", | 882 | DEBUG_ENT("debiting %zu entropy credits from %s%s\n", |
886 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); | 883 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); |
887 | 884 | ||
888 | spin_unlock_irqrestore(&r->lock, flags); | 885 | spin_unlock_irqrestore(&r->lock, flags); |
@@ -957,6 +954,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
957 | ssize_t ret = 0, i; | 954 | ssize_t ret = 0, i; |
958 | __u8 tmp[EXTRACT_SIZE]; | 955 | __u8 tmp[EXTRACT_SIZE]; |
959 | 956 | ||
957 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ | ||
958 | if (fips_enabled && !r->last_data_init) | ||
959 | nbytes += EXTRACT_SIZE; | ||
960 | |||
960 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); | 961 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); |
961 | xfer_secondary_pool(r, nbytes); | 962 | xfer_secondary_pool(r, nbytes); |
962 | nbytes = account(r, nbytes, min, reserved); | 963 | nbytes = account(r, nbytes, min, reserved); |
@@ -967,6 +968,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
967 | if (fips_enabled) { | 968 | if (fips_enabled) { |
968 | unsigned long flags; | 969 | unsigned long flags; |
969 | 970 | ||
971 | |||
972 | /* prime last_data value if need be, per fips 140-2 */ | ||
973 | if (!r->last_data_init) { | ||
974 | spin_lock_irqsave(&r->lock, flags); | ||
975 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
976 | r->last_data_init = true; | ||
977 | nbytes -= EXTRACT_SIZE; | ||
978 | spin_unlock_irqrestore(&r->lock, flags); | ||
979 | extract_buf(r, tmp); | ||
980 | } | ||
981 | |||
970 | spin_lock_irqsave(&r->lock, flags); | 982 | spin_lock_irqsave(&r->lock, flags); |
971 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | 983 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) |
972 | panic("Hardware RNG duplicated output!\n"); | 984 | panic("Hardware RNG duplicated output!\n"); |
@@ -1086,6 +1098,7 @@ static void init_std_data(struct entropy_store *r) | |||
1086 | 1098 | ||
1087 | r->entropy_count = 0; | 1099 | r->entropy_count = 0; |
1088 | r->entropy_total = 0; | 1100 | r->entropy_total = 0; |
1101 | r->last_data_init = false; | ||
1089 | mix_pool_bytes(r, &now, sizeof(now), NULL); | 1102 | mix_pool_bytes(r, &now, sizeof(now), NULL); |
1090 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { | 1103 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { |
1091 | if (!arch_get_random_long(&rv)) | 1104 | if (!arch_get_random_long(&rv)) |
@@ -1142,11 +1155,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
1142 | if (n > SEC_XFER_SIZE) | 1155 | if (n > SEC_XFER_SIZE) |
1143 | n = SEC_XFER_SIZE; | 1156 | n = SEC_XFER_SIZE; |
1144 | 1157 | ||
1145 | DEBUG_ENT("reading %d bits\n", n*8); | 1158 | DEBUG_ENT("reading %zu bits\n", n*8); |
1146 | 1159 | ||
1147 | n = extract_entropy_user(&blocking_pool, buf, n); | 1160 | n = extract_entropy_user(&blocking_pool, buf, n); |
1148 | 1161 | ||
1149 | DEBUG_ENT("read got %d bits (%d still needed)\n", | 1162 | if (n < 0) { |
1163 | retval = n; | ||
1164 | break; | ||
1165 | } | ||
1166 | |||
1167 | DEBUG_ENT("read got %zd bits (%zd still needed)\n", | ||
1150 | n*8, (nbytes-n)*8); | 1168 | n*8, (nbytes-n)*8); |
1151 | 1169 | ||
1152 | if (n == 0) { | 1170 | if (n == 0) { |
@@ -1171,10 +1189,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
1171 | continue; | 1189 | continue; |
1172 | } | 1190 | } |
1173 | 1191 | ||
1174 | if (n < 0) { | ||
1175 | retval = n; | ||
1176 | break; | ||
1177 | } | ||
1178 | count += n; | 1192 | count += n; |
1179 | buf += n; | 1193 | buf += n; |
1180 | nbytes -= n; | 1194 | nbytes -= n; |
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c index 517a8ff7121e..6b4c70f7d23d 100644 --- a/drivers/clk/clk-nomadik.c +++ b/drivers/clk/clk-nomadik.c | |||
@@ -20,6 +20,7 @@ void __init nomadik_clk_init(void) | |||
20 | clk_register_clkdev(clk, NULL, "gpio.2"); | 20 | clk_register_clkdev(clk, NULL, "gpio.2"); |
21 | clk_register_clkdev(clk, NULL, "gpio.3"); | 21 | clk_register_clkdev(clk, NULL, "gpio.3"); |
22 | clk_register_clkdev(clk, NULL, "rng"); | 22 | clk_register_clkdev(clk, NULL, "rng"); |
23 | clk_register_clkdev(clk, NULL, "fsmc-nand"); | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * The 2.4 MHz TIMCLK reference clock is active at boot time, this is | 26 | * The 2.4 MHz TIMCLK reference clock is active at boot time, this is |
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a9151337d5b9..33d20be87db5 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -579,7 +579,7 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo, | |||
579 | * at this point the buffer should be dead, so | 579 | * at this point the buffer should be dead, so |
580 | * no new sync objects can be attached. | 580 | * no new sync objects can be attached. |
581 | */ | 581 | */ |
582 | sync_obj = driver->sync_obj_ref(&bo->sync_obj); | 582 | sync_obj = driver->sync_obj_ref(bo->sync_obj); |
583 | spin_unlock(&bdev->fence_lock); | 583 | spin_unlock(&bdev->fence_lock); |
584 | 584 | ||
585 | atomic_set(&bo->reserved, 0); | 585 | atomic_set(&bo->reserved, 0); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index d6cc77a53c7e..5f306f79da0c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -921,6 +921,7 @@ static int __init i8042_platform_init(void) | |||
921 | int retval; | 921 | int retval; |
922 | 922 | ||
923 | #ifdef CONFIG_X86 | 923 | #ifdef CONFIG_X86 |
924 | u8 a20_on = 0xdf; | ||
924 | /* Just return if pre-detection shows no i8042 controller exist */ | 925 | /* Just return if pre-detection shows no i8042 controller exist */ |
925 | if (!x86_platform.i8042_detect()) | 926 | if (!x86_platform.i8042_detect()) |
926 | return -ENODEV; | 927 | return -ENODEV; |
@@ -960,6 +961,14 @@ static int __init i8042_platform_init(void) | |||
960 | 961 | ||
961 | if (dmi_check_system(i8042_dmi_dritek_table)) | 962 | if (dmi_check_system(i8042_dmi_dritek_table)) |
962 | i8042_dritek = true; | 963 | i8042_dritek = true; |
964 | |||
965 | /* | ||
966 | * A20 was already enabled during early kernel init. But some buggy | ||
967 | * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to | ||
968 | * resume from S3. So we do it here and hope that nothing breaks. | ||
969 | */ | ||
970 | i8042_command(&a20_on, 0x10d1); | ||
971 | i8042_command(NULL, 0x00ff); /* Null command for SMM firmware */ | ||
963 | #endif /* CONFIG_X86 */ | 972 | #endif /* CONFIG_X86 */ |
964 | 973 | ||
965 | return retval; | 974 | return retval; |
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c index 945393129952..7c057a05adb6 100644 --- a/drivers/mtd/ar7part.c +++ b/drivers/mtd/ar7part.c | |||
@@ -26,19 +26,16 @@ | |||
26 | #include <linux/mtd/mtd.h> | 26 | #include <linux/mtd/mtd.h> |
27 | #include <linux/mtd/partitions.h> | 27 | #include <linux/mtd/partitions.h> |
28 | #include <linux/bootmem.h> | 28 | #include <linux/bootmem.h> |
29 | #include <linux/magic.h> | ||
30 | #include <linux/module.h> | 29 | #include <linux/module.h> |
31 | 30 | ||
31 | #include <uapi/linux/magic.h> | ||
32 | |||
32 | #define AR7_PARTS 4 | 33 | #define AR7_PARTS 4 |
33 | #define ROOT_OFFSET 0xe0000 | 34 | #define ROOT_OFFSET 0xe0000 |
34 | 35 | ||
35 | #define LOADER_MAGIC1 le32_to_cpu(0xfeedfa42) | 36 | #define LOADER_MAGIC1 le32_to_cpu(0xfeedfa42) |
36 | #define LOADER_MAGIC2 le32_to_cpu(0xfeed1281) | 37 | #define LOADER_MAGIC2 le32_to_cpu(0xfeed1281) |
37 | 38 | ||
38 | #ifndef SQUASHFS_MAGIC | ||
39 | #define SQUASHFS_MAGIC 0x73717368 | ||
40 | #endif | ||
41 | |||
42 | struct ar7_bin_rec { | 39 | struct ar7_bin_rec { |
43 | unsigned int checksum; | 40 | unsigned int checksum; |
44 | unsigned int length; | 41 | unsigned int length; |
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 63d2a64331f7..6eeb84c81bc2 100644 --- a/drivers/mtd/bcm63xxpart.c +++ b/drivers/mtd/bcm63xxpart.c | |||
@@ -37,8 +37,7 @@ | |||
37 | 37 | ||
38 | #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ | 38 | #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ |
39 | 39 | ||
40 | #define BCM63XX_MIN_CFE_SIZE 0x10000 /* always at least 64KiB */ | 40 | #define BCM63XX_CFE_BLOCK_SIZE 0x10000 /* always at least 64KiB */ |
41 | #define BCM63XX_MIN_NVRAM_SIZE 0x10000 /* always at least 64KiB */ | ||
42 | 41 | ||
43 | #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0 | 42 | #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0 |
44 | 43 | ||
@@ -79,7 +78,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
79 | unsigned int rootfsaddr, kerneladdr, spareaddr; | 78 | unsigned int rootfsaddr, kerneladdr, spareaddr; |
80 | unsigned int rootfslen, kernellen, sparelen, totallen; | 79 | unsigned int rootfslen, kernellen, sparelen, totallen; |
81 | unsigned int cfelen, nvramlen; | 80 | unsigned int cfelen, nvramlen; |
82 | int namelen = 0; | 81 | unsigned int cfe_erasesize; |
83 | int i; | 82 | int i; |
84 | u32 computed_crc; | 83 | u32 computed_crc; |
85 | bool rootfs_first = false; | 84 | bool rootfs_first = false; |
@@ -87,8 +86,11 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
87 | if (bcm63xx_detect_cfe(master)) | 86 | if (bcm63xx_detect_cfe(master)) |
88 | return -EINVAL; | 87 | return -EINVAL; |
89 | 88 | ||
90 | cfelen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_CFE_SIZE); | 89 | cfe_erasesize = max_t(uint32_t, master->erasesize, |
91 | nvramlen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_NVRAM_SIZE); | 90 | BCM63XX_CFE_BLOCK_SIZE); |
91 | |||
92 | cfelen = cfe_erasesize; | ||
93 | nvramlen = cfe_erasesize; | ||
92 | 94 | ||
93 | /* Allocate memory for buffer */ | 95 | /* Allocate memory for buffer */ |
94 | buf = vmalloc(sizeof(struct bcm_tag)); | 96 | buf = vmalloc(sizeof(struct bcm_tag)); |
@@ -121,7 +123,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
121 | kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; | 123 | kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; |
122 | rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE; | 124 | rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE; |
123 | spareaddr = roundup(totallen, master->erasesize) + cfelen; | 125 | spareaddr = roundup(totallen, master->erasesize) + cfelen; |
124 | sparelen = master->size - spareaddr - nvramlen; | ||
125 | 126 | ||
126 | if (rootfsaddr < kerneladdr) { | 127 | if (rootfsaddr < kerneladdr) { |
127 | /* default Broadcom layout */ | 128 | /* default Broadcom layout */ |
@@ -139,19 +140,15 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
139 | rootfslen = 0; | 140 | rootfslen = 0; |
140 | rootfsaddr = 0; | 141 | rootfsaddr = 0; |
141 | spareaddr = cfelen; | 142 | spareaddr = cfelen; |
142 | sparelen = master->size - cfelen - nvramlen; | ||
143 | } | 143 | } |
144 | sparelen = master->size - spareaddr - nvramlen; | ||
144 | 145 | ||
145 | /* Determine number of partitions */ | 146 | /* Determine number of partitions */ |
146 | namelen = 8; | 147 | if (rootfslen > 0) |
147 | if (rootfslen > 0) { | ||
148 | nrparts++; | 148 | nrparts++; |
149 | namelen += 6; | 149 | |
150 | } | 150 | if (kernellen > 0) |
151 | if (kernellen > 0) { | ||
152 | nrparts++; | 151 | nrparts++; |
153 | namelen += 6; | ||
154 | } | ||
155 | 152 | ||
156 | /* Ask kernel for more memory */ | 153 | /* Ask kernel for more memory */ |
157 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); | 154 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); |
@@ -193,17 +190,16 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
193 | parts[curpart].name = "nvram"; | 190 | parts[curpart].name = "nvram"; |
194 | parts[curpart].offset = master->size - nvramlen; | 191 | parts[curpart].offset = master->size - nvramlen; |
195 | parts[curpart].size = nvramlen; | 192 | parts[curpart].size = nvramlen; |
193 | curpart++; | ||
196 | 194 | ||
197 | /* Global partition "linux" to make easy firmware upgrade */ | 195 | /* Global partition "linux" to make easy firmware upgrade */ |
198 | curpart++; | ||
199 | parts[curpart].name = "linux"; | 196 | parts[curpart].name = "linux"; |
200 | parts[curpart].offset = cfelen; | 197 | parts[curpart].offset = cfelen; |
201 | parts[curpart].size = master->size - cfelen - nvramlen; | 198 | parts[curpart].size = master->size - cfelen - nvramlen; |
202 | 199 | ||
203 | for (i = 0; i < nrparts; i++) | 200 | for (i = 0; i < nrparts; i++) |
204 | pr_info("Partition %d is %s offset %lx and length %lx\n", i, | 201 | pr_info("Partition %d is %s offset %llx and length %llx\n", i, |
205 | parts[i].name, (long unsigned int)(parts[i].offset), | 202 | parts[i].name, parts[i].offset, parts[i].size); |
206 | (long unsigned int)(parts[i].size)); | ||
207 | 203 | ||
208 | pr_info("Spare partition is offset %x and length %x\n", spareaddr, | 204 | pr_info("Spare partition is offset %x and length %x\n", spareaddr, |
209 | sparelen); | 205 | sparelen); |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 5ff5c4a16943..b86197286f24 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -1536,8 +1536,20 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1536 | UDELAY(map, chip, adr, 1); | 1536 | UDELAY(map, chip, adr, 1); |
1537 | } | 1537 | } |
1538 | 1538 | ||
1539 | /* reset on all failures. */ | 1539 | /* |
1540 | map_write( map, CMD(0xF0), chip->start ); | 1540 | * Recovery from write-buffer programming failures requires |
1541 | * the write-to-buffer-reset sequence. Since the last part | ||
1542 | * of the sequence also works as a normal reset, we can run | ||
1543 | * the same commands regardless of why we are here. | ||
1544 | * See e.g. | ||
1545 | * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf | ||
1546 | */ | ||
1547 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1548 | cfi->device_type, NULL); | ||
1549 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1550 | cfi->device_type, NULL); | ||
1551 | cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi, | ||
1552 | cfi->device_type, NULL); | ||
1541 | xip_enable(map, chip, adr); | 1553 | xip_enable(map, chip, adr); |
1542 | /* FIXME - should have reset delay before continuing */ | 1554 | /* FIXME - should have reset delay before continuing */ |
1543 | 1555 | ||
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index aed1b8a63c9f..c533f27d863f 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
@@ -56,8 +56,8 @@ | |||
56 | 56 | ||
57 | 57 | ||
58 | /* special size referring to all the remaining space in a partition */ | 58 | /* special size referring to all the remaining space in a partition */ |
59 | #define SIZE_REMAINING UINT_MAX | 59 | #define SIZE_REMAINING ULLONG_MAX |
60 | #define OFFSET_CONTINUOUS UINT_MAX | 60 | #define OFFSET_CONTINUOUS ULLONG_MAX |
61 | 61 | ||
62 | struct cmdline_mtd_partition { | 62 | struct cmdline_mtd_partition { |
63 | struct cmdline_mtd_partition *next; | 63 | struct cmdline_mtd_partition *next; |
@@ -89,7 +89,7 @@ static struct mtd_partition * newpart(char *s, | |||
89 | int extra_mem_size) | 89 | int extra_mem_size) |
90 | { | 90 | { |
91 | struct mtd_partition *parts; | 91 | struct mtd_partition *parts; |
92 | unsigned long size, offset = OFFSET_CONTINUOUS; | 92 | unsigned long long size, offset = OFFSET_CONTINUOUS; |
93 | char *name; | 93 | char *name; |
94 | int name_len; | 94 | int name_len; |
95 | unsigned char *extra_mem; | 95 | unsigned char *extra_mem; |
@@ -104,7 +104,8 @@ static struct mtd_partition * newpart(char *s, | |||
104 | } else { | 104 | } else { |
105 | size = memparse(s, &s); | 105 | size = memparse(s, &s); |
106 | if (size < PAGE_SIZE) { | 106 | if (size < PAGE_SIZE) { |
107 | printk(KERN_ERR ERRP "partition size too small (%lx)\n", size); | 107 | printk(KERN_ERR ERRP "partition size too small (%llx)\n", |
108 | size); | ||
108 | return ERR_PTR(-EINVAL); | 109 | return ERR_PTR(-EINVAL); |
109 | } | 110 | } |
110 | } | 111 | } |
@@ -296,7 +297,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, | |||
296 | struct mtd_partition **pparts, | 297 | struct mtd_partition **pparts, |
297 | struct mtd_part_parser_data *data) | 298 | struct mtd_part_parser_data *data) |
298 | { | 299 | { |
299 | unsigned long offset; | 300 | unsigned long long offset; |
300 | int i, err; | 301 | int i, err; |
301 | struct cmdline_mtd_partition *part; | 302 | struct cmdline_mtd_partition *part; |
302 | const char *mtd_id = master->name; | 303 | const char *mtd_id = master->name; |
@@ -308,48 +309,52 @@ static int parse_cmdline_partitions(struct mtd_info *master, | |||
308 | return err; | 309 | return err; |
309 | } | 310 | } |
310 | 311 | ||
312 | /* | ||
313 | * Search for the partition definition matching master->name. | ||
314 | * If master->name is not set, stop at first partition definition. | ||
315 | */ | ||
311 | for (part = partitions; part; part = part->next) { | 316 | for (part = partitions; part; part = part->next) { |
312 | if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) { | 317 | if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id))) |
313 | for (i = 0, offset = 0; i < part->num_parts; i++) { | 318 | break; |
314 | if (part->parts[i].offset == OFFSET_CONTINUOUS) | 319 | } |
315 | part->parts[i].offset = offset; | 320 | |
316 | else | 321 | if (!part) |
317 | offset = part->parts[i].offset; | 322 | return 0; |
318 | 323 | ||
319 | if (part->parts[i].size == SIZE_REMAINING) | 324 | for (i = 0, offset = 0; i < part->num_parts; i++) { |
320 | part->parts[i].size = master->size - offset; | 325 | if (part->parts[i].offset == OFFSET_CONTINUOUS) |
321 | 326 | part->parts[i].offset = offset; | |
322 | if (part->parts[i].size == 0) { | 327 | else |
323 | printk(KERN_WARNING ERRP | 328 | offset = part->parts[i].offset; |
324 | "%s: skipping zero sized partition\n", | 329 | |
325 | part->mtd_id); | 330 | if (part->parts[i].size == SIZE_REMAINING) |
326 | part->num_parts--; | 331 | part->parts[i].size = master->size - offset; |
327 | memmove(&part->parts[i], | 332 | |
328 | &part->parts[i + 1], | 333 | if (part->parts[i].size == 0) { |
329 | sizeof(*part->parts) * (part->num_parts - i)); | 334 | printk(KERN_WARNING ERRP |
330 | continue; | 335 | "%s: skipping zero sized partition\n", |
331 | } | 336 | part->mtd_id); |
332 | 337 | part->num_parts--; | |
333 | if (offset + part->parts[i].size > master->size) { | 338 | memmove(&part->parts[i], &part->parts[i + 1], |
334 | printk(KERN_WARNING ERRP | 339 | sizeof(*part->parts) * (part->num_parts - i)); |
335 | "%s: partitioning exceeds flash size, truncating\n", | 340 | continue; |
336 | part->mtd_id); | ||
337 | part->parts[i].size = master->size - offset; | ||
338 | } | ||
339 | offset += part->parts[i].size; | ||
340 | } | ||
341 | |||
342 | *pparts = kmemdup(part->parts, | ||
343 | sizeof(*part->parts) * part->num_parts, | ||
344 | GFP_KERNEL); | ||
345 | if (!*pparts) | ||
346 | return -ENOMEM; | ||
347 | |||
348 | return part->num_parts; | ||
349 | } | 341 | } |
342 | |||
343 | if (offset + part->parts[i].size > master->size) { | ||
344 | printk(KERN_WARNING ERRP | ||
345 | "%s: partitioning exceeds flash size, truncating\n", | ||
346 | part->mtd_id); | ||
347 | part->parts[i].size = master->size - offset; | ||
348 | } | ||
349 | offset += part->parts[i].size; | ||
350 | } | 350 | } |
351 | 351 | ||
352 | return 0; | 352 | *pparts = kmemdup(part->parts, sizeof(*part->parts) * part->num_parts, |
353 | GFP_KERNEL); | ||
354 | if (!*pparts) | ||
355 | return -ENOMEM; | ||
356 | |||
357 | return part->num_parts; | ||
353 | } | 358 | } |
354 | 359 | ||
355 | 360 | ||
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 2dc5a6f3fd57..4714584aa993 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c | |||
@@ -66,7 +66,7 @@ out: | |||
66 | return err; | 66 | return err; |
67 | } | 67 | } |
68 | 68 | ||
69 | static int __devexit bcm47xxsflash_remove(struct platform_device *pdev) | 69 | static int bcm47xxsflash_remove(struct platform_device *pdev) |
70 | { | 70 | { |
71 | struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); | 71 | struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); |
72 | 72 | ||
@@ -77,7 +77,7 @@ static int __devexit bcm47xxsflash_remove(struct platform_device *pdev) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | static struct platform_driver bcma_sflash_driver = { | 79 | static struct platform_driver bcma_sflash_driver = { |
80 | .remove = __devexit_p(bcm47xxsflash_remove), | 80 | .remove = bcm47xxsflash_remove, |
81 | .driver = { | 81 | .driver = { |
82 | .name = "bcma_sflash", | 82 | .name = "bcma_sflash", |
83 | .owner = THIS_MODULE, | 83 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 681e2ee0f2d6..e081bfeaaf7d 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -62,6 +62,7 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) | |||
62 | memset(page_address(page), 0xff, PAGE_SIZE); | 62 | memset(page_address(page), 0xff, PAGE_SIZE); |
63 | set_page_dirty(page); | 63 | set_page_dirty(page); |
64 | unlock_page(page); | 64 | unlock_page(page); |
65 | balance_dirty_pages_ratelimited(mapping); | ||
65 | break; | 66 | break; |
66 | } | 67 | } |
67 | 68 | ||
@@ -152,6 +153,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, | |||
152 | memcpy(page_address(page) + offset, buf, cpylen); | 153 | memcpy(page_address(page) + offset, buf, cpylen); |
153 | set_page_dirty(page); | 154 | set_page_dirty(page); |
154 | unlock_page(page); | 155 | unlock_page(page); |
156 | balance_dirty_pages_ratelimited(mapping); | ||
155 | } | 157 | } |
156 | page_cache_release(page); | 158 | page_cache_release(page); |
157 | 159 | ||
@@ -433,7 +435,7 @@ static int __init block2mtd_init(void) | |||
433 | } | 435 | } |
434 | 436 | ||
435 | 437 | ||
436 | static void __devexit block2mtd_exit(void) | 438 | static void block2mtd_exit(void) |
437 | { | 439 | { |
438 | struct list_head *pos, *next; | 440 | struct list_head *pos, *next; |
439 | 441 | ||
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index d34d83b8f9c2..8510ccb9c6f0 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
@@ -1440,7 +1440,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | |||
1440 | oobdelta = mtd->ecclayout->oobavail; | 1440 | oobdelta = mtd->ecclayout->oobavail; |
1441 | break; | 1441 | break; |
1442 | default: | 1442 | default: |
1443 | oobdelta = 0; | 1443 | return -EINVAL; |
1444 | } | 1444 | } |
1445 | if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % oobdelta) || | 1445 | if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % oobdelta) || |
1446 | (ofs % DOC_LAYOUT_PAGE_SIZE)) | 1446 | (ofs % DOC_LAYOUT_PAGE_SIZE)) |
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 706b847b46b3..88b3fd3e18a7 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c | |||
@@ -70,8 +70,6 @@ static unsigned long __initdata doc_locations[] = { | |||
70 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, | 70 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, |
71 | 0xe8000, 0xea000, 0xec000, 0xee000, | 71 | 0xe8000, 0xea000, 0xec000, 0xee000, |
72 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ | 72 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ |
73 | #else | ||
74 | #warning Unknown architecture for DiskOnChip. No default probe locations defined | ||
75 | #endif | 73 | #endif |
76 | 0xffffffff }; | 74 | 0xffffffff }; |
77 | 75 | ||
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 03838bab1f59..4eeeb2d7f6ea 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -73,14 +73,6 @@ | |||
73 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ | 73 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ |
74 | #define MAX_CMD_SIZE 5 | 74 | #define MAX_CMD_SIZE 5 |
75 | 75 | ||
76 | #ifdef CONFIG_M25PXX_USE_FAST_READ | ||
77 | #define OPCODE_READ OPCODE_FAST_READ | ||
78 | #define FAST_READ_DUMMY_BYTE 1 | ||
79 | #else | ||
80 | #define OPCODE_READ OPCODE_NORM_READ | ||
81 | #define FAST_READ_DUMMY_BYTE 0 | ||
82 | #endif | ||
83 | |||
84 | #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) | 76 | #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) |
85 | 77 | ||
86 | /****************************************************************************/ | 78 | /****************************************************************************/ |
@@ -93,6 +85,7 @@ struct m25p { | |||
93 | u16 addr_width; | 85 | u16 addr_width; |
94 | u8 erase_opcode; | 86 | u8 erase_opcode; |
95 | u8 *command; | 87 | u8 *command; |
88 | bool fast_read; | ||
96 | }; | 89 | }; |
97 | 90 | ||
98 | static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) | 91 | static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) |
@@ -168,6 +161,7 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) | |||
168 | { | 161 | { |
169 | switch (JEDEC_MFR(jedec_id)) { | 162 | switch (JEDEC_MFR(jedec_id)) { |
170 | case CFI_MFR_MACRONIX: | 163 | case CFI_MFR_MACRONIX: |
164 | case 0xEF /* winbond */: | ||
171 | flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; | 165 | flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; |
172 | return spi_write(flash->spi, flash->command, 1); | 166 | return spi_write(flash->spi, flash->command, 1); |
173 | default: | 167 | default: |
@@ -342,6 +336,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
342 | struct m25p *flash = mtd_to_m25p(mtd); | 336 | struct m25p *flash = mtd_to_m25p(mtd); |
343 | struct spi_transfer t[2]; | 337 | struct spi_transfer t[2]; |
344 | struct spi_message m; | 338 | struct spi_message m; |
339 | uint8_t opcode; | ||
345 | 340 | ||
346 | pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), | 341 | pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev), |
347 | __func__, (u32)from, len); | 342 | __func__, (u32)from, len); |
@@ -354,7 +349,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
354 | * Should add 1 byte DUMMY_BYTE. | 349 | * Should add 1 byte DUMMY_BYTE. |
355 | */ | 350 | */ |
356 | t[0].tx_buf = flash->command; | 351 | t[0].tx_buf = flash->command; |
357 | t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE; | 352 | t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0); |
358 | spi_message_add_tail(&t[0], &m); | 353 | spi_message_add_tail(&t[0], &m); |
359 | 354 | ||
360 | t[1].rx_buf = buf; | 355 | t[1].rx_buf = buf; |
@@ -376,12 +371,14 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
376 | */ | 371 | */ |
377 | 372 | ||
378 | /* Set up the write data buffer. */ | 373 | /* Set up the write data buffer. */ |
379 | flash->command[0] = OPCODE_READ; | 374 | opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ; |
375 | flash->command[0] = opcode; | ||
380 | m25p_addr2cmd(flash, from, flash->command); | 376 | m25p_addr2cmd(flash, from, flash->command); |
381 | 377 | ||
382 | spi_sync(flash->spi, &m); | 378 | spi_sync(flash->spi, &m); |
383 | 379 | ||
384 | *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE; | 380 | *retlen = m.actual_length - m25p_cmdsz(flash) - |
381 | (flash->fast_read ? 1 : 0); | ||
385 | 382 | ||
386 | mutex_unlock(&flash->lock); | 383 | mutex_unlock(&flash->lock); |
387 | 384 | ||
@@ -664,7 +661,8 @@ static const struct spi_device_id m25p_ids[] = { | |||
664 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, | 661 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, |
665 | 662 | ||
666 | /* Micron */ | 663 | /* Micron */ |
667 | { "n25q128", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, | 664 | { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, |
665 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, | ||
668 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, | 666 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, |
669 | 667 | ||
670 | /* Spansion -- single (large) sector size only, at least | 668 | /* Spansion -- single (large) sector size only, at least |
@@ -745,6 +743,8 @@ static const struct spi_device_id m25p_ids[] = { | |||
745 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 743 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
746 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 744 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
747 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, | 745 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, |
746 | { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, | ||
747 | { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, | ||
748 | 748 | ||
749 | /* Catalyst / On Semiconductor -- non-JEDEC */ | 749 | /* Catalyst / On Semiconductor -- non-JEDEC */ |
750 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, | 750 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, |
@@ -756,7 +756,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
756 | }; | 756 | }; |
757 | MODULE_DEVICE_TABLE(spi, m25p_ids); | 757 | MODULE_DEVICE_TABLE(spi, m25p_ids); |
758 | 758 | ||
759 | static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | 759 | static const struct spi_device_id *jedec_probe(struct spi_device *spi) |
760 | { | 760 | { |
761 | int tmp; | 761 | int tmp; |
762 | u8 code = OPCODE_RDID; | 762 | u8 code = OPCODE_RDID; |
@@ -801,7 +801,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
801 | * matches what the READ command supports, at least until this driver | 801 | * matches what the READ command supports, at least until this driver |
802 | * understands FAST_READ (for clocks over 25 MHz). | 802 | * understands FAST_READ (for clocks over 25 MHz). |
803 | */ | 803 | */ |
804 | static int __devinit m25p_probe(struct spi_device *spi) | 804 | static int m25p_probe(struct spi_device *spi) |
805 | { | 805 | { |
806 | const struct spi_device_id *id = spi_get_device_id(spi); | 806 | const struct spi_device_id *id = spi_get_device_id(spi); |
807 | struct flash_platform_data *data; | 807 | struct flash_platform_data *data; |
@@ -809,9 +809,10 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
809 | struct flash_info *info; | 809 | struct flash_info *info; |
810 | unsigned i; | 810 | unsigned i; |
811 | struct mtd_part_parser_data ppdata; | 811 | struct mtd_part_parser_data ppdata; |
812 | struct device_node __maybe_unused *np = spi->dev.of_node; | ||
812 | 813 | ||
813 | #ifdef CONFIG_MTD_OF_PARTS | 814 | #ifdef CONFIG_MTD_OF_PARTS |
814 | if (!of_device_is_available(spi->dev.of_node)) | 815 | if (!of_device_is_available(np)) |
815 | return -ENODEV; | 816 | return -ENODEV; |
816 | #endif | 817 | #endif |
817 | 818 | ||
@@ -863,7 +864,8 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
863 | flash = kzalloc(sizeof *flash, GFP_KERNEL); | 864 | flash = kzalloc(sizeof *flash, GFP_KERNEL); |
864 | if (!flash) | 865 | if (!flash) |
865 | return -ENOMEM; | 866 | return -ENOMEM; |
866 | flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL); | 867 | flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), |
868 | GFP_KERNEL); | ||
867 | if (!flash->command) { | 869 | if (!flash->command) { |
868 | kfree(flash); | 870 | kfree(flash); |
869 | return -ENOMEM; | 871 | return -ENOMEM; |
@@ -920,6 +922,16 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
920 | flash->page_size = info->page_size; | 922 | flash->page_size = info->page_size; |
921 | flash->mtd.writebufsize = flash->page_size; | 923 | flash->mtd.writebufsize = flash->page_size; |
922 | 924 | ||
925 | flash->fast_read = false; | ||
926 | #ifdef CONFIG_OF | ||
927 | if (np && of_property_read_bool(np, "m25p,fast-read")) | ||
928 | flash->fast_read = true; | ||
929 | #endif | ||
930 | |||
931 | #ifdef CONFIG_M25PXX_USE_FAST_READ | ||
932 | flash->fast_read = true; | ||
933 | #endif | ||
934 | |||
923 | if (info->addr_width) | 935 | if (info->addr_width) |
924 | flash->addr_width = info->addr_width; | 936 | flash->addr_width = info->addr_width; |
925 | else { | 937 | else { |
@@ -961,7 +973,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
961 | } | 973 | } |
962 | 974 | ||
963 | 975 | ||
964 | static int __devexit m25p_remove(struct spi_device *spi) | 976 | static int m25p_remove(struct spi_device *spi) |
965 | { | 977 | { |
966 | struct m25p *flash = dev_get_drvdata(&spi->dev); | 978 | struct m25p *flash = dev_get_drvdata(&spi->dev); |
967 | int status; | 979 | int status; |
@@ -983,7 +995,7 @@ static struct spi_driver m25p80_driver = { | |||
983 | }, | 995 | }, |
984 | .id_table = m25p_ids, | 996 | .id_table = m25p_ids, |
985 | .probe = m25p_probe, | 997 | .probe = m25p_probe, |
986 | .remove = __devexit_p(m25p_remove), | 998 | .remove = m25p_remove, |
987 | 999 | ||
988 | /* REVISIT: many of these chips have deep power-down modes, which | 1000 | /* REVISIT: many of these chips have deep power-down modes, which |
989 | * should clearly be entered on suspend() to minimize power use. | 1001 | * should clearly be entered on suspend() to minimize power use. |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 928fb0e6d73a..ea7ea7b595d8 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -618,7 +618,7 @@ static char *otp_setup(struct mtd_info *device, char revision) | |||
618 | /* | 618 | /* |
619 | * Register DataFlash device with MTD subsystem. | 619 | * Register DataFlash device with MTD subsystem. |
620 | */ | 620 | */ |
621 | static int __devinit | 621 | static int |
622 | add_dataflash_otp(struct spi_device *spi, char *name, | 622 | add_dataflash_otp(struct spi_device *spi, char *name, |
623 | int nr_pages, int pagesize, int pageoffset, char revision) | 623 | int nr_pages, int pagesize, int pageoffset, char revision) |
624 | { | 624 | { |
@@ -679,7 +679,7 @@ add_dataflash_otp(struct spi_device *spi, char *name, | |||
679 | return err; | 679 | return err; |
680 | } | 680 | } |
681 | 681 | ||
682 | static inline int __devinit | 682 | static inline int |
683 | add_dataflash(struct spi_device *spi, char *name, | 683 | add_dataflash(struct spi_device *spi, char *name, |
684 | int nr_pages, int pagesize, int pageoffset) | 684 | int nr_pages, int pagesize, int pageoffset) |
685 | { | 685 | { |
@@ -705,7 +705,7 @@ struct flash_info { | |||
705 | #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ | 705 | #define IS_POW2PS 0x0001 /* uses 2^N byte pages */ |
706 | }; | 706 | }; |
707 | 707 | ||
708 | static struct flash_info __devinitdata dataflash_data [] = { | 708 | static struct flash_info dataflash_data[] = { |
709 | 709 | ||
710 | /* | 710 | /* |
711 | * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, | 711 | * NOTE: chips with SUP_POW2PS (rev D and up) need two entries, |
@@ -740,7 +740,7 @@ static struct flash_info __devinitdata dataflash_data [] = { | |||
740 | { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, | 740 | { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, |
741 | }; | 741 | }; |
742 | 742 | ||
743 | static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | 743 | static struct flash_info *jedec_probe(struct spi_device *spi) |
744 | { | 744 | { |
745 | int tmp; | 745 | int tmp; |
746 | uint8_t code = OP_READ_ID; | 746 | uint8_t code = OP_READ_ID; |
@@ -823,7 +823,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) | |||
823 | * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 | 823 | * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 |
824 | * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 | 824 | * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 |
825 | */ | 825 | */ |
826 | static int __devinit dataflash_probe(struct spi_device *spi) | 826 | static int dataflash_probe(struct spi_device *spi) |
827 | { | 827 | { |
828 | int status; | 828 | int status; |
829 | struct flash_info *info; | 829 | struct flash_info *info; |
@@ -897,7 +897,7 @@ static int __devinit dataflash_probe(struct spi_device *spi) | |||
897 | return status; | 897 | return status; |
898 | } | 898 | } |
899 | 899 | ||
900 | static int __devexit dataflash_remove(struct spi_device *spi) | 900 | static int dataflash_remove(struct spi_device *spi) |
901 | { | 901 | { |
902 | struct dataflash *flash = dev_get_drvdata(&spi->dev); | 902 | struct dataflash *flash = dev_get_drvdata(&spi->dev); |
903 | int status; | 903 | int status; |
@@ -920,7 +920,7 @@ static struct spi_driver dataflash_driver = { | |||
920 | }, | 920 | }, |
921 | 921 | ||
922 | .probe = dataflash_probe, | 922 | .probe = dataflash_probe, |
923 | .remove = __devexit_p(dataflash_remove), | 923 | .remove = dataflash_remove, |
924 | 924 | ||
925 | /* FIXME: investigate suspend and resume... */ | 925 | /* FIXME: investigate suspend and resume... */ |
926 | }; | 926 | }; |
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index dcc3c9511530..2d2c2a5d4d2a 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c | |||
@@ -756,7 +756,7 @@ err_probe: | |||
756 | 756 | ||
757 | 757 | ||
758 | #ifdef CONFIG_OF | 758 | #ifdef CONFIG_OF |
759 | static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, | 759 | static int spear_smi_probe_config_dt(struct platform_device *pdev, |
760 | struct device_node *np) | 760 | struct device_node *np) |
761 | { | 761 | { |
762 | struct spear_smi_plat_data *pdata = dev_get_platdata(&pdev->dev); | 762 | struct spear_smi_plat_data *pdata = dev_get_platdata(&pdev->dev); |
@@ -799,7 +799,7 @@ static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, | |||
799 | return 0; | 799 | return 0; |
800 | } | 800 | } |
801 | #else | 801 | #else |
802 | static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, | 802 | static int spear_smi_probe_config_dt(struct platform_device *pdev, |
803 | struct device_node *np) | 803 | struct device_node *np) |
804 | { | 804 | { |
805 | return -ENOSYS; | 805 | return -ENOSYS; |
@@ -901,7 +901,7 @@ static int spear_smi_setup_banks(struct platform_device *pdev, | |||
901 | * and do proper init for any found one. | 901 | * and do proper init for any found one. |
902 | * Returns 0 on success, non zero otherwise | 902 | * Returns 0 on success, non zero otherwise |
903 | */ | 903 | */ |
904 | static int __devinit spear_smi_probe(struct platform_device *pdev) | 904 | static int spear_smi_probe(struct platform_device *pdev) |
905 | { | 905 | { |
906 | struct device_node *np = pdev->dev.of_node; | 906 | struct device_node *np = pdev->dev.of_node; |
907 | struct spear_smi_plat_data *pdata = NULL; | 907 | struct spear_smi_plat_data *pdata = NULL; |
@@ -1016,7 +1016,7 @@ err: | |||
1016 | * | 1016 | * |
1017 | * free all allocations and delete the partitions. | 1017 | * free all allocations and delete the partitions. |
1018 | */ | 1018 | */ |
1019 | static int __devexit spear_smi_remove(struct platform_device *pdev) | 1019 | static int spear_smi_remove(struct platform_device *pdev) |
1020 | { | 1020 | { |
1021 | struct spear_smi *dev; | 1021 | struct spear_smi *dev; |
1022 | struct spear_snor_flash *flash; | 1022 | struct spear_snor_flash *flash; |
@@ -1092,20 +1092,9 @@ static struct platform_driver spear_smi_driver = { | |||
1092 | #endif | 1092 | #endif |
1093 | }, | 1093 | }, |
1094 | .probe = spear_smi_probe, | 1094 | .probe = spear_smi_probe, |
1095 | .remove = __devexit_p(spear_smi_remove), | 1095 | .remove = spear_smi_remove, |
1096 | }; | 1096 | }; |
1097 | 1097 | module_platform_driver(spear_smi_driver); | |
1098 | static int spear_smi_init(void) | ||
1099 | { | ||
1100 | return platform_driver_register(&spear_smi_driver); | ||
1101 | } | ||
1102 | module_init(spear_smi_init); | ||
1103 | |||
1104 | static void spear_smi_exit(void) | ||
1105 | { | ||
1106 | platform_driver_unregister(&spear_smi_driver); | ||
1107 | } | ||
1108 | module_exit(spear_smi_exit); | ||
1109 | 1098 | ||
1110 | MODULE_LICENSE("GPL"); | 1099 | MODULE_LICENSE("GPL"); |
1111 | MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>"); | 1100 | MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>"); |
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index ab8a2f4c8d60..8091b0163694 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -64,7 +64,7 @@ struct flash_info { | |||
64 | 64 | ||
65 | #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd) | 65 | #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd) |
66 | 66 | ||
67 | static struct flash_info __devinitdata sst25l_flash_info[] = { | 67 | static struct flash_info sst25l_flash_info[] = { |
68 | {"sst25lf020a", 0xbf43, 256, 1024, 4096}, | 68 | {"sst25lf020a", 0xbf43, 256, 1024, 4096}, |
69 | {"sst25lf040a", 0xbf44, 256, 2048, 4096}, | 69 | {"sst25lf040a", 0xbf44, 256, 2048, 4096}, |
70 | }; | 70 | }; |
@@ -313,7 +313,7 @@ out: | |||
313 | return ret; | 313 | return ret; |
314 | } | 314 | } |
315 | 315 | ||
316 | static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi) | 316 | static struct flash_info *sst25l_match_device(struct spi_device *spi) |
317 | { | 317 | { |
318 | struct flash_info *flash_info = NULL; | 318 | struct flash_info *flash_info = NULL; |
319 | struct spi_message m; | 319 | struct spi_message m; |
@@ -353,7 +353,7 @@ static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi) | |||
353 | return flash_info; | 353 | return flash_info; |
354 | } | 354 | } |
355 | 355 | ||
356 | static int __devinit sst25l_probe(struct spi_device *spi) | 356 | static int sst25l_probe(struct spi_device *spi) |
357 | { | 357 | { |
358 | struct flash_info *flash_info; | 358 | struct flash_info *flash_info; |
359 | struct sst25l_flash *flash; | 359 | struct sst25l_flash *flash; |
@@ -411,7 +411,7 @@ static int __devinit sst25l_probe(struct spi_device *spi) | |||
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
413 | 413 | ||
414 | static int __devexit sst25l_remove(struct spi_device *spi) | 414 | static int sst25l_remove(struct spi_device *spi) |
415 | { | 415 | { |
416 | struct sst25l_flash *flash = dev_get_drvdata(&spi->dev); | 416 | struct sst25l_flash *flash = dev_get_drvdata(&spi->dev); |
417 | int ret; | 417 | int ret; |
@@ -428,7 +428,7 @@ static struct spi_driver sst25l_driver = { | |||
428 | .owner = THIS_MODULE, | 428 | .owner = THIS_MODULE, |
429 | }, | 429 | }, |
430 | .probe = sst25l_probe, | 430 | .probe = sst25l_probe, |
431 | .remove = __devexit_p(sst25l_remove), | 431 | .remove = sst25l_remove, |
432 | }; | 432 | }; |
433 | 433 | ||
434 | module_spi_driver(sst25l_driver); | 434 | module_spi_driver(sst25l_driver); |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index df304868bebb..62ba82c396c2 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -358,13 +358,6 @@ config MTD_IXP2000 | |||
358 | IXP2000 based board and would like to use the flash chips on it, | 358 | IXP2000 based board and would like to use the flash chips on it, |
359 | say 'Y'. | 359 | say 'Y'. |
360 | 360 | ||
361 | config MTD_FORTUNET | ||
362 | tristate "CFI Flash device mapped on the FortuNet board" | ||
363 | depends on MTD_CFI && SA1100_FORTUNET | ||
364 | help | ||
365 | This enables access to the Flash on the FortuNet board. If you | ||
366 | have such a board, say 'Y'. | ||
367 | |||
368 | config MTD_AUTCPU12 | 361 | config MTD_AUTCPU12 |
369 | bool "NV-RAM mapping AUTCPU12 board" | 362 | bool "NV-RAM mapping AUTCPU12 board" |
370 | depends on ARCH_AUTCPU12 | 363 | depends on ARCH_AUTCPU12 |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index a0240edd1961..4ded28711bc1 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -39,7 +39,6 @@ obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o | |||
39 | obj-$(CONFIG_MTD_PCI) += pci.o | 39 | obj-$(CONFIG_MTD_PCI) += pci.o |
40 | obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o | 40 | obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o |
41 | obj-$(CONFIG_MTD_IMPA7) += impa7.o | 41 | obj-$(CONFIG_MTD_IMPA7) += impa7.o |
42 | obj-$(CONFIG_MTD_FORTUNET) += fortunet.o | ||
43 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o | 42 | obj-$(CONFIG_MTD_UCLINUX) += uclinux.o |
44 | obj-$(CONFIG_MTD_NETtel) += nettel.o | 43 | obj-$(CONFIG_MTD_NETtel) += nettel.o |
45 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o | 44 | obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o |
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index e2875d6fe129..f7207b0a76dc 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c | |||
@@ -100,8 +100,8 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window) | |||
100 | } | 100 | } |
101 | 101 | ||
102 | 102 | ||
103 | static int __devinit amd76xrom_init_one (struct pci_dev *pdev, | 103 | static int amd76xrom_init_one(struct pci_dev *pdev, |
104 | const struct pci_device_id *ent) | 104 | const struct pci_device_id *ent) |
105 | { | 105 | { |
106 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 106 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
107 | u8 byte; | 107 | u8 byte; |
@@ -289,7 +289,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, | |||
289 | } | 289 | } |
290 | 290 | ||
291 | 291 | ||
292 | static void __devexit amd76xrom_remove_one (struct pci_dev *pdev) | 292 | static void amd76xrom_remove_one(struct pci_dev *pdev) |
293 | { | 293 | { |
294 | struct amd76xrom_window *window = &amd76xrom_window; | 294 | struct amd76xrom_window *window = &amd76xrom_window; |
295 | 295 | ||
@@ -347,4 +347,3 @@ module_exit(cleanup_amd76xrom); | |||
347 | MODULE_LICENSE("GPL"); | 347 | MODULE_LICENSE("GPL"); |
348 | MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>"); | 348 | MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>"); |
349 | MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge"); | 349 | MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge"); |
350 | |||
diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index 76fb594bb1d9..a2dc2ae4b24e 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c | |||
@@ -33,7 +33,7 @@ struct autcpu12_nvram_priv { | |||
33 | struct map_info map; | 33 | struct map_info map; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | static int __devinit autcpu12_nvram_probe(struct platform_device *pdev) | 36 | static int autcpu12_nvram_probe(struct platform_device *pdev) |
37 | { | 37 | { |
38 | map_word tmp, save0, save1; | 38 | map_word tmp, save0, save1; |
39 | struct resource *res; | 39 | struct resource *res; |
@@ -105,7 +105,7 @@ static int __devinit autcpu12_nvram_probe(struct platform_device *pdev) | |||
105 | return -ENOMEM; | 105 | return -ENOMEM; |
106 | } | 106 | } |
107 | 107 | ||
108 | static int __devexit autcpu12_nvram_remove(struct platform_device *pdev) | 108 | static int autcpu12_nvram_remove(struct platform_device *pdev) |
109 | { | 109 | { |
110 | struct autcpu12_nvram_priv *priv = platform_get_drvdata(pdev); | 110 | struct autcpu12_nvram_priv *priv = platform_get_drvdata(pdev); |
111 | 111 | ||
@@ -121,7 +121,7 @@ static struct platform_driver autcpu12_nvram_driver = { | |||
121 | .owner = THIS_MODULE, | 121 | .owner = THIS_MODULE, |
122 | }, | 122 | }, |
123 | .probe = autcpu12_nvram_probe, | 123 | .probe = autcpu12_nvram_probe, |
124 | .remove = __devexit_p(autcpu12_nvram_remove), | 124 | .remove = autcpu12_nvram_remove, |
125 | }; | 125 | }; |
126 | module_platform_driver(autcpu12_nvram_driver); | 126 | module_platform_driver(autcpu12_nvram_driver); |
127 | 127 | ||
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index ef5cde84a8b3..f833edfaab79 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c | |||
@@ -30,7 +30,8 @@ | |||
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | #include <asm/unaligned.h> | 31 | #include <asm/unaligned.h> |
32 | 32 | ||
33 | #define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) | 33 | #define pr_devinit(fmt, args...) \ |
34 | ({ static const char __fmt[] = fmt; printk(__fmt, ## args); }) | ||
34 | 35 | ||
35 | #define DRIVER_NAME "bfin-async-flash" | 36 | #define DRIVER_NAME "bfin-async-flash" |
36 | 37 | ||
@@ -123,7 +124,7 @@ static void bfin_flash_copy_to(struct map_info *map, unsigned long to, const voi | |||
123 | 124 | ||
124 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; | 125 | static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; |
125 | 126 | ||
126 | static int __devinit bfin_flash_probe(struct platform_device *pdev) | 127 | static int bfin_flash_probe(struct platform_device *pdev) |
127 | { | 128 | { |
128 | int ret; | 129 | int ret; |
129 | struct physmap_flash_data *pdata = pdev->dev.platform_data; | 130 | struct physmap_flash_data *pdata = pdev->dev.platform_data; |
@@ -172,7 +173,7 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) | |||
172 | return 0; | 173 | return 0; |
173 | } | 174 | } |
174 | 175 | ||
175 | static int __devexit bfin_flash_remove(struct platform_device *pdev) | 176 | static int bfin_flash_remove(struct platform_device *pdev) |
176 | { | 177 | { |
177 | struct async_state *state = platform_get_drvdata(pdev); | 178 | struct async_state *state = platform_get_drvdata(pdev); |
178 | gpio_free(state->enet_flash_pin); | 179 | gpio_free(state->enet_flash_pin); |
@@ -184,7 +185,7 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev) | |||
184 | 185 | ||
185 | static struct platform_driver bfin_flash_driver = { | 186 | static struct platform_driver bfin_flash_driver = { |
186 | .probe = bfin_flash_probe, | 187 | .probe = bfin_flash_probe, |
187 | .remove = __devexit_p(bfin_flash_remove), | 188 | .remove = bfin_flash_remove, |
188 | .driver = { | 189 | .driver = { |
189 | .name = DRIVER_NAME, | 190 | .name = DRIVER_NAME, |
190 | }, | 191 | }, |
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 3d0e762fa5f2..586a1c77e48a 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c | |||
@@ -112,8 +112,8 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | 114 | ||
115 | static int __devinit ck804xrom_init_one (struct pci_dev *pdev, | 115 | static int ck804xrom_init_one(struct pci_dev *pdev, |
116 | const struct pci_device_id *ent) | 116 | const struct pci_device_id *ent) |
117 | { | 117 | { |
118 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 118 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
119 | u8 byte; | 119 | u8 byte; |
@@ -320,7 +320,7 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev, | |||
320 | } | 320 | } |
321 | 321 | ||
322 | 322 | ||
323 | static void __devexit ck804xrom_remove_one (struct pci_dev *pdev) | 323 | static void ck804xrom_remove_one(struct pci_dev *pdev) |
324 | { | 324 | { |
325 | struct ck804xrom_window *window = &ck804xrom_window; | 325 | struct ck804xrom_window *window = &ck804xrom_window; |
326 | 326 | ||
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 08322b1c3e81..ff8681a25831 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c | |||
@@ -144,7 +144,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window) | |||
144 | pci_dev_put(window->pdev); | 144 | pci_dev_put(window->pdev); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int __devinit esb2rom_init_one(struct pci_dev *pdev, | 147 | static int esb2rom_init_one(struct pci_dev *pdev, |
148 | const struct pci_device_id *ent) | 148 | const struct pci_device_id *ent) |
149 | { | 149 | { |
150 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 150 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
@@ -378,13 +378,13 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev, | |||
378 | return 0; | 378 | return 0; |
379 | } | 379 | } |
380 | 380 | ||
381 | static void __devexit esb2rom_remove_one (struct pci_dev *pdev) | 381 | static void esb2rom_remove_one(struct pci_dev *pdev) |
382 | { | 382 | { |
383 | struct esb2rom_window *window = &esb2rom_window; | 383 | struct esb2rom_window *window = &esb2rom_window; |
384 | esb2rom_cleanup(window); | 384 | esb2rom_cleanup(window); |
385 | } | 385 | } |
386 | 386 | ||
387 | static struct pci_device_id esb2rom_pci_tbl[] __devinitdata = { | 387 | static struct pci_device_id esb2rom_pci_tbl[] = { |
388 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, | 388 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, |
389 | PCI_ANY_ID, PCI_ANY_ID, }, | 389 | PCI_ANY_ID, PCI_ANY_ID, }, |
390 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, | 390 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, |
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c deleted file mode 100644 index 956e2e4f30ea..000000000000 --- a/drivers/mtd/maps/fortunet.c +++ /dev/null | |||
@@ -1,277 +0,0 @@ | |||
1 | /* fortunet.c memory map | ||
2 | * | ||
3 | */ | ||
4 | |||
5 | #include <linux/module.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/string.h> | ||
10 | |||
11 | #include <linux/mtd/mtd.h> | ||
12 | #include <linux/mtd/map.h> | ||
13 | #include <linux/mtd/partitions.h> | ||
14 | |||
15 | #include <asm/io.h> | ||
16 | |||
17 | #define MAX_NUM_REGIONS 4 | ||
18 | #define MAX_NUM_PARTITIONS 8 | ||
19 | |||
20 | #define DEF_WINDOW_ADDR_PHY 0x00000000 | ||
21 | #define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes | ||
22 | |||
23 | #define MTD_FORTUNET_PK "MTD FortuNet: " | ||
24 | |||
25 | #define MAX_NAME_SIZE 128 | ||
26 | |||
27 | struct map_region | ||
28 | { | ||
29 | int window_addr_physical; | ||
30 | int altbankwidth; | ||
31 | struct map_info map_info; | ||
32 | struct mtd_info *mymtd; | ||
33 | struct mtd_partition parts[MAX_NUM_PARTITIONS]; | ||
34 | char map_name[MAX_NAME_SIZE]; | ||
35 | char parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE]; | ||
36 | }; | ||
37 | |||
38 | static struct map_region map_regions[MAX_NUM_REGIONS]; | ||
39 | static int map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0}; | ||
40 | static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0}; | ||
41 | |||
42 | |||
43 | |||
44 | struct map_info default_map = { | ||
45 | .size = DEF_WINDOW_SIZE, | ||
46 | .bankwidth = 4, | ||
47 | }; | ||
48 | |||
49 | static char * __init get_string_option(char *dest,int dest_size,char *sor) | ||
50 | { | ||
51 | if(!dest_size) | ||
52 | return sor; | ||
53 | dest_size--; | ||
54 | while(*sor) | ||
55 | { | ||
56 | if(*sor==',') | ||
57 | { | ||
58 | sor++; | ||
59 | break; | ||
60 | } | ||
61 | else if(*sor=='\"') | ||
62 | { | ||
63 | sor++; | ||
64 | while(*sor) | ||
65 | { | ||
66 | if(*sor=='\"') | ||
67 | { | ||
68 | sor++; | ||
69 | break; | ||
70 | } | ||
71 | *dest = *sor; | ||
72 | dest++; | ||
73 | sor++; | ||
74 | dest_size--; | ||
75 | if(!dest_size) | ||
76 | { | ||
77 | *dest = 0; | ||
78 | return sor; | ||
79 | } | ||
80 | } | ||
81 | } | ||
82 | else | ||
83 | { | ||
84 | *dest = *sor; | ||
85 | dest++; | ||
86 | sor++; | ||
87 | dest_size--; | ||
88 | if(!dest_size) | ||
89 | { | ||
90 | *dest = 0; | ||
91 | return sor; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | *dest = 0; | ||
96 | return sor; | ||
97 | } | ||
98 | |||
99 | static int __init MTD_New_Region(char *line) | ||
100 | { | ||
101 | char string[MAX_NAME_SIZE]; | ||
102 | int params[6]; | ||
103 | get_options (get_string_option(string,sizeof(string),line),6,params); | ||
104 | if(params[0]<1) | ||
105 | { | ||
106 | printk(MTD_FORTUNET_PK "Bad parameters for MTD Region " | ||
107 | " name,region-number[,base,size,bankwidth,altbankwidth]\n"); | ||
108 | return 1; | ||
109 | } | ||
110 | if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS)) | ||
111 | { | ||
112 | printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n", | ||
113 | params[1],MAX_NUM_REGIONS-1); | ||
114 | return 1; | ||
115 | } | ||
116 | memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]])); | ||
117 | memcpy(&map_regions[params[1]].map_info, | ||
118 | &default_map,sizeof(map_regions[params[1]].map_info)); | ||
119 | map_regions_set[params[1]] = 1; | ||
120 | map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY; | ||
121 | map_regions[params[1]].altbankwidth = 2; | ||
122 | map_regions[params[1]].mymtd = NULL; | ||
123 | map_regions[params[1]].map_info.name = map_regions[params[1]].map_name; | ||
124 | strcpy(map_regions[params[1]].map_info.name,string); | ||
125 | if(params[0]>1) | ||
126 | { | ||
127 | map_regions[params[1]].window_addr_physical = params[2]; | ||
128 | } | ||
129 | if(params[0]>2) | ||
130 | { | ||
131 | map_regions[params[1]].map_info.size = params[3]; | ||
132 | } | ||
133 | if(params[0]>3) | ||
134 | { | ||
135 | map_regions[params[1]].map_info.bankwidth = params[4]; | ||
136 | } | ||
137 | if(params[0]>4) | ||
138 | { | ||
139 | map_regions[params[1]].altbankwidth = params[5]; | ||
140 | } | ||
141 | return 1; | ||
142 | } | ||
143 | |||
144 | static int __init MTD_New_Partition(char *line) | ||
145 | { | ||
146 | char string[MAX_NAME_SIZE]; | ||
147 | int params[4]; | ||
148 | get_options (get_string_option(string,sizeof(string),line),4,params); | ||
149 | if(params[0]<3) | ||
150 | { | ||
151 | printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition " | ||
152 | " name,region-number,size,offset\n"); | ||
153 | return 1; | ||
154 | } | ||
155 | if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS)) | ||
156 | { | ||
157 | printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n", | ||
158 | params[1],MAX_NUM_REGIONS-1); | ||
159 | return 1; | ||
160 | } | ||
161 | if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS) | ||
162 | { | ||
163 | printk(MTD_FORTUNET_PK "Out of space for partition in this region\n"); | ||
164 | return 1; | ||
165 | } | ||
166 | map_regions[params[1]].parts[map_regions_parts[params[1]]].name = | ||
167 | map_regions[params[1]]. parts_name[map_regions_parts[params[1]]]; | ||
168 | strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string); | ||
169 | map_regions[params[1]].parts[map_regions_parts[params[1]]].size = | ||
170 | params[2]; | ||
171 | map_regions[params[1]].parts[map_regions_parts[params[1]]].offset = | ||
172 | params[3]; | ||
173 | map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0; | ||
174 | map_regions_parts[params[1]]++; | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | __setup("MTD_Region=", MTD_New_Region); | ||
179 | __setup("MTD_Partition=", MTD_New_Partition); | ||
180 | |||
181 | /* Backwards-spelling-compatibility */ | ||
182 | __setup("MTD_Partion=", MTD_New_Partition); | ||
183 | |||
184 | static int __init init_fortunet(void) | ||
185 | { | ||
186 | int ix,iy; | ||
187 | for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++) | ||
188 | { | ||
189 | if(map_regions_parts[ix]&&(!map_regions_set[ix])) | ||
190 | { | ||
191 | printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n", | ||
192 | ix); | ||
193 | memset(&map_regions[ix],0,sizeof(map_regions[ix])); | ||
194 | memcpy(&map_regions[ix].map_info,&default_map, | ||
195 | sizeof(map_regions[ix].map_info)); | ||
196 | map_regions_set[ix] = 1; | ||
197 | map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY; | ||
198 | map_regions[ix].altbankwidth = 2; | ||
199 | map_regions[ix].mymtd = NULL; | ||
200 | map_regions[ix].map_info.name = map_regions[ix].map_name; | ||
201 | strcpy(map_regions[ix].map_info.name,"FORTUNET"); | ||
202 | } | ||
203 | if(map_regions_set[ix]) | ||
204 | { | ||
205 | iy++; | ||
206 | printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically " | ||
207 | " address %x size %x\n", | ||
208 | map_regions[ix].map_info.name, | ||
209 | map_regions[ix].window_addr_physical, | ||
210 | map_regions[ix].map_info.size); | ||
211 | |||
212 | map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical, | ||
213 | |||
214 | map_regions[ix].map_info.virt = | ||
215 | ioremap_nocache( | ||
216 | map_regions[ix].window_addr_physical, | ||
217 | map_regions[ix].map_info.size); | ||
218 | if(!map_regions[ix].map_info.virt) | ||
219 | { | ||
220 | int j = 0; | ||
221 | printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n", | ||
222 | map_regions[ix].map_info.name); | ||
223 | for (j = 0 ; j < ix; j++) | ||
224 | iounmap(map_regions[j].map_info.virt); | ||
225 | return -ENXIO; | ||
226 | } | ||
227 | simple_map_init(&map_regions[ix].map_info); | ||
228 | |||
229 | printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n", | ||
230 | map_regions[ix].map_info.name, | ||
231 | map_regions[ix].map_info.virt); | ||
232 | map_regions[ix].mymtd = do_map_probe("cfi_probe", | ||
233 | &map_regions[ix].map_info); | ||
234 | if((!map_regions[ix].mymtd)&&( | ||
235 | map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth)) | ||
236 | { | ||
237 | printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth " | ||
238 | "for %s flash.\n", | ||
239 | map_regions[ix].map_info.name); | ||
240 | map_regions[ix].map_info.bankwidth = | ||
241 | map_regions[ix].altbankwidth; | ||
242 | map_regions[ix].mymtd = do_map_probe("cfi_probe", | ||
243 | &map_regions[ix].map_info); | ||
244 | } | ||
245 | map_regions[ix].mymtd->owner = THIS_MODULE; | ||
246 | mtd_device_register(map_regions[ix].mymtd, | ||
247 | map_regions[ix].parts, | ||
248 | map_regions_parts[ix]); | ||
249 | } | ||
250 | } | ||
251 | if(iy) | ||
252 | return 0; | ||
253 | return -ENXIO; | ||
254 | } | ||
255 | |||
256 | static void __exit cleanup_fortunet(void) | ||
257 | { | ||
258 | int ix; | ||
259 | for(ix=0;ix<MAX_NUM_REGIONS;ix++) | ||
260 | { | ||
261 | if(map_regions_set[ix]) | ||
262 | { | ||
263 | if( map_regions[ix].mymtd ) | ||
264 | { | ||
265 | mtd_device_unregister(map_regions[ix].mymtd); | ||
266 | map_destroy( map_regions[ix].mymtd ); | ||
267 | } | ||
268 | iounmap((void *)map_regions[ix].map_info.virt); | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | |||
273 | module_init(init_fortunet); | ||
274 | module_exit(cleanup_fortunet); | ||
275 | |||
276 | MODULE_AUTHOR("FortuNet, Inc."); | ||
277 | MODULE_DESCRIPTION("MTD map driver for FortuNet boards"); | ||
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index e4de96ba52b3..7b643de2500b 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -26,7 +26,8 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | 28 | ||
29 | #define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) | 29 | #define pr_devinit(fmt, args...) \ |
30 | ({ static const char __fmt[] = fmt; printk(__fmt, ## args); }) | ||
30 | 31 | ||
31 | #define DRIVER_NAME "gpio-addr-flash" | 32 | #define DRIVER_NAME "gpio-addr-flash" |
32 | #define PFX DRIVER_NAME ": " | 33 | #define PFX DRIVER_NAME ": " |
@@ -142,7 +143,8 @@ static void gf_write(struct map_info *map, map_word d1, unsigned long ofs) | |||
142 | * | 143 | * |
143 | * See gf_copy_from() caveat. | 144 | * See gf_copy_from() caveat. |
144 | */ | 145 | */ |
145 | static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) | 146 | static void gf_copy_to(struct map_info *map, unsigned long to, |
147 | const void *from, ssize_t len) | ||
146 | { | 148 | { |
147 | struct async_state *state = gf_map_info_to_state(map); | 149 | struct async_state *state = gf_map_info_to_state(map); |
148 | 150 | ||
@@ -185,7 +187,7 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; | |||
185 | * ... | 187 | * ... |
186 | * }; | 188 | * }; |
187 | */ | 189 | */ |
188 | static int __devinit gpio_flash_probe(struct platform_device *pdev) | 190 | static int gpio_flash_probe(struct platform_device *pdev) |
189 | { | 191 | { |
190 | size_t i, arr_size; | 192 | size_t i, arr_size; |
191 | struct physmap_flash_data *pdata; | 193 | struct physmap_flash_data *pdata; |
@@ -258,7 +260,7 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) | |||
258 | return 0; | 260 | return 0; |
259 | } | 261 | } |
260 | 262 | ||
261 | static int __devexit gpio_flash_remove(struct platform_device *pdev) | 263 | static int gpio_flash_remove(struct platform_device *pdev) |
262 | { | 264 | { |
263 | struct async_state *state = platform_get_drvdata(pdev); | 265 | struct async_state *state = platform_get_drvdata(pdev); |
264 | size_t i = 0; | 266 | size_t i = 0; |
@@ -273,7 +275,7 @@ static int __devexit gpio_flash_remove(struct platform_device *pdev) | |||
273 | 275 | ||
274 | static struct platform_driver gpio_flash_driver = { | 276 | static struct platform_driver gpio_flash_driver = { |
275 | .probe = gpio_flash_probe, | 277 | .probe = gpio_flash_probe, |
276 | .remove = __devexit_p(gpio_flash_remove), | 278 | .remove = gpio_flash_remove, |
277 | .driver = { | 279 | .driver = { |
278 | .name = DRIVER_NAME, | 280 | .name = DRIVER_NAME, |
279 | }, | 281 | }, |
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index 6689dcb3124d..c7478e18f485 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c | |||
@@ -84,8 +84,8 @@ static void ichxrom_cleanup(struct ichxrom_window *window) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | 86 | ||
87 | static int __devinit ichxrom_init_one (struct pci_dev *pdev, | 87 | static int ichxrom_init_one(struct pci_dev *pdev, |
88 | const struct pci_device_id *ent) | 88 | const struct pci_device_id *ent) |
89 | { | 89 | { |
90 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 90 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
91 | struct ichxrom_window *window = &ichxrom_window; | 91 | struct ichxrom_window *window = &ichxrom_window; |
@@ -315,13 +315,13 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, | |||
315 | } | 315 | } |
316 | 316 | ||
317 | 317 | ||
318 | static void __devexit ichxrom_remove_one (struct pci_dev *pdev) | 318 | static void ichxrom_remove_one(struct pci_dev *pdev) |
319 | { | 319 | { |
320 | struct ichxrom_window *window = &ichxrom_window; | 320 | struct ichxrom_window *window = &ichxrom_window; |
321 | ichxrom_cleanup(window); | 321 | ichxrom_cleanup(window); |
322 | } | 322 | } |
323 | 323 | ||
324 | static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = { | 324 | static struct pci_device_id ichxrom_pci_tbl[] = { |
325 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, | 325 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, |
326 | PCI_ANY_ID, PCI_ANY_ID, }, | 326 | PCI_ANY_ID, PCI_ANY_ID, }, |
327 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, | 327 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, |
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c index 93f03175c82d..3ee2ad1dcbe7 100644 --- a/drivers/mtd/maps/intel_vr_nor.c +++ b/drivers/mtd/maps/intel_vr_nor.c | |||
@@ -63,24 +63,24 @@ struct vr_nor_mtd { | |||
63 | #define TIMING_BYTE_EN (1 << 0) /* 8-bit vs 16-bit bus */ | 63 | #define TIMING_BYTE_EN (1 << 0) /* 8-bit vs 16-bit bus */ |
64 | #define TIMING_MASK 0x3FFF0000 | 64 | #define TIMING_MASK 0x3FFF0000 |
65 | 65 | ||
66 | static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p) | 66 | static void vr_nor_destroy_partitions(struct vr_nor_mtd *p) |
67 | { | 67 | { |
68 | mtd_device_unregister(p->info); | 68 | mtd_device_unregister(p->info); |
69 | } | 69 | } |
70 | 70 | ||
71 | static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p) | 71 | static int vr_nor_init_partitions(struct vr_nor_mtd *p) |
72 | { | 72 | { |
73 | /* register the flash bank */ | 73 | /* register the flash bank */ |
74 | /* partition the flash bank */ | 74 | /* partition the flash bank */ |
75 | return mtd_device_parse_register(p->info, NULL, NULL, NULL, 0); | 75 | return mtd_device_parse_register(p->info, NULL, NULL, NULL, 0); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) | 78 | static void vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p) |
79 | { | 79 | { |
80 | map_destroy(p->info); | 80 | map_destroy(p->info); |
81 | } | 81 | } |
82 | 82 | ||
83 | static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p) | 83 | static int vr_nor_mtd_setup(struct vr_nor_mtd *p) |
84 | { | 84 | { |
85 | static const char *probe_types[] = | 85 | static const char *probe_types[] = |
86 | { "cfi_probe", "jedec_probe", NULL }; | 86 | { "cfi_probe", "jedec_probe", NULL }; |
@@ -96,7 +96,7 @@ static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p) | |||
96 | return 0; | 96 | return 0; |
97 | } | 97 | } |
98 | 98 | ||
99 | static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p) | 99 | static void vr_nor_destroy_maps(struct vr_nor_mtd *p) |
100 | { | 100 | { |
101 | unsigned int exp_timing_cs0; | 101 | unsigned int exp_timing_cs0; |
102 | 102 | ||
@@ -116,7 +116,7 @@ static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p) | |||
116 | * Initialize the map_info structure and map the flash. | 116 | * Initialize the map_info structure and map the flash. |
117 | * Returns 0 on success, nonzero otherwise. | 117 | * Returns 0 on success, nonzero otherwise. |
118 | */ | 118 | */ |
119 | static int __devinit vr_nor_init_maps(struct vr_nor_mtd *p) | 119 | static int vr_nor_init_maps(struct vr_nor_mtd *p) |
120 | { | 120 | { |
121 | unsigned long csr_phys, csr_len; | 121 | unsigned long csr_phys, csr_len; |
122 | unsigned long win_phys, win_len; | 122 | unsigned long win_phys, win_len; |
@@ -176,7 +176,7 @@ static struct pci_device_id vr_nor_pci_ids[] = { | |||
176 | {0,} | 176 | {0,} |
177 | }; | 177 | }; |
178 | 178 | ||
179 | static void __devexit vr_nor_pci_remove(struct pci_dev *dev) | 179 | static void vr_nor_pci_remove(struct pci_dev *dev) |
180 | { | 180 | { |
181 | struct vr_nor_mtd *p = pci_get_drvdata(dev); | 181 | struct vr_nor_mtd *p = pci_get_drvdata(dev); |
182 | 182 | ||
@@ -189,7 +189,7 @@ static void __devexit vr_nor_pci_remove(struct pci_dev *dev) | |||
189 | pci_disable_device(dev); | 189 | pci_disable_device(dev); |
190 | } | 190 | } |
191 | 191 | ||
192 | static int __devinit | 192 | static int |
193 | vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 193 | vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
194 | { | 194 | { |
195 | struct vr_nor_mtd *p = NULL; | 195 | struct vr_nor_mtd *p = NULL; |
@@ -256,7 +256,7 @@ vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
256 | static struct pci_driver vr_nor_pci_driver = { | 256 | static struct pci_driver vr_nor_pci_driver = { |
257 | .name = DRV_NAME, | 257 | .name = DRV_NAME, |
258 | .probe = vr_nor_pci_probe, | 258 | .probe = vr_nor_pci_probe, |
259 | .remove = __devexit_p(vr_nor_pci_remove), | 259 | .remove = vr_nor_pci_remove, |
260 | .id_table = vr_nor_pci_ids, | 260 | .id_table = vr_nor_pci_ids, |
261 | }; | 261 | }; |
262 | 262 | ||
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index c03456f17004..3c3c791eb96a 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c | |||
@@ -45,7 +45,7 @@ struct ltq_mtd { | |||
45 | }; | 45 | }; |
46 | 46 | ||
47 | static const char ltq_map_name[] = "ltq_nor"; | 47 | static const char ltq_map_name[] = "ltq_nor"; |
48 | static const char *ltq_probe_types[] __devinitconst = { | 48 | static const char *ltq_probe_types[] = { |
49 | "cmdlinepart", "ofpart", NULL }; | 49 | "cmdlinepart", "ofpart", NULL }; |
50 | 50 | ||
51 | static map_word | 51 | static map_word |
@@ -109,7 +109,7 @@ ltq_copy_to(struct map_info *map, unsigned long to, | |||
109 | spin_unlock_irqrestore(&ebu_lock, flags); | 109 | spin_unlock_irqrestore(&ebu_lock, flags); |
110 | } | 110 | } |
111 | 111 | ||
112 | static int __devinit | 112 | static int |
113 | ltq_mtd_probe(struct platform_device *pdev) | 113 | ltq_mtd_probe(struct platform_device *pdev) |
114 | { | 114 | { |
115 | struct mtd_part_parser_data ppdata; | 115 | struct mtd_part_parser_data ppdata; |
@@ -185,7 +185,7 @@ err_out: | |||
185 | return err; | 185 | return err; |
186 | } | 186 | } |
187 | 187 | ||
188 | static int __devexit | 188 | static int |
189 | ltq_mtd_remove(struct platform_device *pdev) | 189 | ltq_mtd_remove(struct platform_device *pdev) |
190 | { | 190 | { |
191 | struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); | 191 | struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); |
@@ -209,7 +209,7 @@ MODULE_DEVICE_TABLE(of, ltq_mtd_match); | |||
209 | 209 | ||
210 | static struct platform_driver ltq_mtd_driver = { | 210 | static struct platform_driver ltq_mtd_driver = { |
211 | .probe = ltq_mtd_probe, | 211 | .probe = ltq_mtd_probe, |
212 | .remove = __devexit_p(ltq_mtd_remove), | 212 | .remove = ltq_mtd_remove, |
213 | .driver = { | 213 | .driver = { |
214 | .name = "ltq-nor", | 214 | .name = "ltq-nor", |
215 | .owner = THIS_MODULE, | 215 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c index 3c7ad17fca78..ab0fead56b83 100644 --- a/drivers/mtd/maps/latch-addr-flash.c +++ b/drivers/mtd/maps/latch-addr-flash.c | |||
@@ -125,7 +125,7 @@ static int latch_addr_flash_remove(struct platform_device *dev) | |||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
127 | 127 | ||
128 | static int __devinit latch_addr_flash_probe(struct platform_device *dev) | 128 | static int latch_addr_flash_probe(struct platform_device *dev) |
129 | { | 129 | { |
130 | struct latch_addr_flash_data *latch_addr_data; | 130 | struct latch_addr_flash_data *latch_addr_data; |
131 | struct latch_addr_flash_info *info; | 131 | struct latch_addr_flash_info *info; |
@@ -218,7 +218,7 @@ done: | |||
218 | 218 | ||
219 | static struct platform_driver latch_addr_flash_driver = { | 219 | static struct platform_driver latch_addr_flash_driver = { |
220 | .probe = latch_addr_flash_probe, | 220 | .probe = latch_addr_flash_probe, |
221 | .remove = __devexit_p(latch_addr_flash_remove), | 221 | .remove = latch_addr_flash_remove, |
222 | .driver = { | 222 | .driver = { |
223 | .name = DRIVER_NAME, | 223 | .name = DRIVER_NAME, |
224 | }, | 224 | }, |
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 1c30c1a307f4..ed82914966f5 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c | |||
@@ -253,7 +253,7 @@ static struct pci_device_id mtd_pci_ids[] = { | |||
253 | * Generic code follows. | 253 | * Generic code follows. |
254 | */ | 254 | */ |
255 | 255 | ||
256 | static int __devinit | 256 | static int |
257 | mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 257 | mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
258 | { | 258 | { |
259 | struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data; | 259 | struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data; |
@@ -308,7 +308,7 @@ out: | |||
308 | return err; | 308 | return err; |
309 | } | 309 | } |
310 | 310 | ||
311 | static void __devexit | 311 | static void |
312 | mtd_pci_remove(struct pci_dev *dev) | 312 | mtd_pci_remove(struct pci_dev *dev) |
313 | { | 313 | { |
314 | struct mtd_info *mtd = pci_get_drvdata(dev); | 314 | struct mtd_info *mtd = pci_get_drvdata(dev); |
@@ -326,7 +326,7 @@ mtd_pci_remove(struct pci_dev *dev) | |||
326 | static struct pci_driver mtd_pci_driver = { | 326 | static struct pci_driver mtd_pci_driver = { |
327 | .name = "MTD PCI", | 327 | .name = "MTD PCI", |
328 | .probe = mtd_pci_probe, | 328 | .probe = mtd_pci_probe, |
329 | .remove = __devexit_p(mtd_pci_remove), | 329 | .remove = mtd_pci_remove, |
330 | .id_table = mtd_pci_ids, | 330 | .id_table = mtd_pci_ids, |
331 | }; | 331 | }; |
332 | 332 | ||
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 6f19acadb06c..37cdc201652f 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -77,7 +77,7 @@ static int of_flash_remove(struct platform_device *dev) | |||
77 | /* Helper function to handle probing of the obsolete "direct-mapped" | 77 | /* Helper function to handle probing of the obsolete "direct-mapped" |
78 | * compatible binding, which has an extra "probe-type" property | 78 | * compatible binding, which has an extra "probe-type" property |
79 | * describing the type of flash probe necessary. */ | 79 | * describing the type of flash probe necessary. */ |
80 | static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, | 80 | static struct mtd_info *obsolete_probe(struct platform_device *dev, |
81 | struct map_info *map) | 81 | struct map_info *map) |
82 | { | 82 | { |
83 | struct device_node *dp = dev->dev.of_node; | 83 | struct device_node *dp = dev->dev.of_node; |
@@ -116,7 +116,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, | |||
116 | information. */ | 116 | information. */ |
117 | static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", | 117 | static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", |
118 | "ofpart", "ofoldpart", NULL }; | 118 | "ofpart", "ofoldpart", NULL }; |
119 | static const char ** __devinit of_get_probes(struct device_node *dp) | 119 | static const char **of_get_probes(struct device_node *dp) |
120 | { | 120 | { |
121 | const char *cp; | 121 | const char *cp; |
122 | int cplen; | 122 | int cplen; |
@@ -145,14 +145,14 @@ static const char ** __devinit of_get_probes(struct device_node *dp) | |||
145 | return res; | 145 | return res; |
146 | } | 146 | } |
147 | 147 | ||
148 | static void __devinit of_free_probes(const char **probes) | 148 | static void of_free_probes(const char **probes) |
149 | { | 149 | { |
150 | if (probes != part_probe_types_def) | 150 | if (probes != part_probe_types_def) |
151 | kfree(probes); | 151 | kfree(probes); |
152 | } | 152 | } |
153 | 153 | ||
154 | static struct of_device_id of_flash_match[]; | 154 | static struct of_device_id of_flash_match[]; |
155 | static int __devinit of_flash_probe(struct platform_device *dev) | 155 | static int of_flash_probe(struct platform_device *dev) |
156 | { | 156 | { |
157 | const char **part_probe_types; | 157 | const char **part_probe_types; |
158 | const struct of_device_id *match; | 158 | const struct of_device_id *match; |
@@ -170,6 +170,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
170 | resource_size_t res_size; | 170 | resource_size_t res_size; |
171 | struct mtd_part_parser_data ppdata; | 171 | struct mtd_part_parser_data ppdata; |
172 | bool map_indirect; | 172 | bool map_indirect; |
173 | const char *mtd_name; | ||
173 | 174 | ||
174 | match = of_match_device(of_flash_match, &dev->dev); | 175 | match = of_match_device(of_flash_match, &dev->dev); |
175 | if (!match) | 176 | if (!match) |
@@ -178,6 +179,8 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
178 | 179 | ||
179 | reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32); | 180 | reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32); |
180 | 181 | ||
182 | of_property_read_string(dp, "linux,mtd-name", &mtd_name); | ||
183 | |||
181 | /* | 184 | /* |
182 | * Get number of "reg" tuples. Scan for MTD devices on area's | 185 | * Get number of "reg" tuples. Scan for MTD devices on area's |
183 | * described by each "reg" region. This makes it possible (including | 186 | * described by each "reg" region. This makes it possible (including |
@@ -234,7 +237,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
234 | goto err_out; | 237 | goto err_out; |
235 | } | 238 | } |
236 | 239 | ||
237 | info->list[i].map.name = dev_name(&dev->dev); | 240 | info->list[i].map.name = mtd_name ?: dev_name(&dev->dev); |
238 | info->list[i].map.phys = res.start; | 241 | info->list[i].map.phys = res.start; |
239 | info->list[i].map.size = res_size; | 242 | info->list[i].map.size = res_size; |
240 | info->list[i].map.bankwidth = be32_to_cpup(width); | 243 | info->list[i].map.bankwidth = be32_to_cpup(width); |
@@ -282,6 +285,7 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
282 | } | 285 | } |
283 | 286 | ||
284 | err = 0; | 287 | err = 0; |
288 | info->cmtd = NULL; | ||
285 | if (info->list_size == 1) { | 289 | if (info->list_size == 1) { |
286 | info->cmtd = info->list[0].mtd; | 290 | info->cmtd = info->list[0].mtd; |
287 | } else if (info->list_size > 1) { | 291 | } else if (info->list_size > 1) { |
@@ -290,9 +294,10 @@ static int __devinit of_flash_probe(struct platform_device *dev) | |||
290 | */ | 294 | */ |
291 | info->cmtd = mtd_concat_create(mtd_list, info->list_size, | 295 | info->cmtd = mtd_concat_create(mtd_list, info->list_size, |
292 | dev_name(&dev->dev)); | 296 | dev_name(&dev->dev)); |
293 | if (info->cmtd == NULL) | ||
294 | err = -ENXIO; | ||
295 | } | 297 | } |
298 | if (info->cmtd == NULL) | ||
299 | err = -ENXIO; | ||
300 | |||
296 | if (err) | 301 | if (err) |
297 | goto err_out; | 302 | goto err_out; |
298 | 303 | ||
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c index 65bd1cd4d627..afea93b515d5 100644 --- a/drivers/mtd/maps/pismo.c +++ b/drivers/mtd/maps/pismo.c | |||
@@ -58,7 +58,7 @@ static void pismo_set_vpp(struct platform_device *pdev, int on) | |||
58 | pismo->vpp(pismo->vpp_data, on); | 58 | pismo->vpp(pismo->vpp_data, on); |
59 | } | 59 | } |
60 | 60 | ||
61 | static unsigned int __devinit pismo_width_to_bytes(unsigned int width) | 61 | static unsigned int pismo_width_to_bytes(unsigned int width) |
62 | { | 62 | { |
63 | width &= 15; | 63 | width &= 15; |
64 | if (width > 2) | 64 | if (width > 2) |
@@ -66,7 +66,7 @@ static unsigned int __devinit pismo_width_to_bytes(unsigned int width) | |||
66 | return 1 << width; | 66 | return 1 << width; |
67 | } | 67 | } |
68 | 68 | ||
69 | static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf, | 69 | static int pismo_eeprom_read(struct i2c_client *client, void *buf, |
70 | u8 addr, size_t size) | 70 | u8 addr, size_t size) |
71 | { | 71 | { |
72 | int ret; | 72 | int ret; |
@@ -88,7 +88,7 @@ static int __devinit pismo_eeprom_read(struct i2c_client *client, void *buf, | |||
88 | return ret == ARRAY_SIZE(msg) ? size : -EIO; | 88 | return ret == ARRAY_SIZE(msg) ? size : -EIO; |
89 | } | 89 | } |
90 | 90 | ||
91 | static int __devinit pismo_add_device(struct pismo_data *pismo, int i, | 91 | static int pismo_add_device(struct pismo_data *pismo, int i, |
92 | struct pismo_mem *region, const char *name, void *pdata, size_t psize) | 92 | struct pismo_mem *region, const char *name, void *pdata, size_t psize) |
93 | { | 93 | { |
94 | struct platform_device *dev; | 94 | struct platform_device *dev; |
@@ -129,7 +129,7 @@ static int __devinit pismo_add_device(struct pismo_data *pismo, int i, | |||
129 | return ret; | 129 | return ret; |
130 | } | 130 | } |
131 | 131 | ||
132 | static int __devinit pismo_add_nor(struct pismo_data *pismo, int i, | 132 | static int pismo_add_nor(struct pismo_data *pismo, int i, |
133 | struct pismo_mem *region) | 133 | struct pismo_mem *region) |
134 | { | 134 | { |
135 | struct physmap_flash_data data = { | 135 | struct physmap_flash_data data = { |
@@ -143,7 +143,7 @@ static int __devinit pismo_add_nor(struct pismo_data *pismo, int i, | |||
143 | &data, sizeof(data)); | 143 | &data, sizeof(data)); |
144 | } | 144 | } |
145 | 145 | ||
146 | static int __devinit pismo_add_sram(struct pismo_data *pismo, int i, | 146 | static int pismo_add_sram(struct pismo_data *pismo, int i, |
147 | struct pismo_mem *region) | 147 | struct pismo_mem *region) |
148 | { | 148 | { |
149 | struct platdata_mtd_ram data = { | 149 | struct platdata_mtd_ram data = { |
@@ -154,7 +154,7 @@ static int __devinit pismo_add_sram(struct pismo_data *pismo, int i, | |||
154 | &data, sizeof(data)); | 154 | &data, sizeof(data)); |
155 | } | 155 | } |
156 | 156 | ||
157 | static void __devinit pismo_add_one(struct pismo_data *pismo, int i, | 157 | static void pismo_add_one(struct pismo_data *pismo, int i, |
158 | const struct pismo_cs_block *cs, phys_addr_t base) | 158 | const struct pismo_cs_block *cs, phys_addr_t base) |
159 | { | 159 | { |
160 | struct device *dev = &pismo->client->dev; | 160 | struct device *dev = &pismo->client->dev; |
@@ -197,7 +197,7 @@ static void __devinit pismo_add_one(struct pismo_data *pismo, int i, | |||
197 | } | 197 | } |
198 | } | 198 | } |
199 | 199 | ||
200 | static int __devexit pismo_remove(struct i2c_client *client) | 200 | static int pismo_remove(struct i2c_client *client) |
201 | { | 201 | { |
202 | struct pismo_data *pismo = i2c_get_clientdata(client); | 202 | struct pismo_data *pismo = i2c_get_clientdata(client); |
203 | int i; | 203 | int i; |
@@ -210,7 +210,7 @@ static int __devexit pismo_remove(struct i2c_client *client) | |||
210 | return 0; | 210 | return 0; |
211 | } | 211 | } |
212 | 212 | ||
213 | static int __devinit pismo_probe(struct i2c_client *client, | 213 | static int pismo_probe(struct i2c_client *client, |
214 | const struct i2c_device_id *id) | 214 | const struct i2c_device_id *id) |
215 | { | 215 | { |
216 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 216 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
@@ -267,7 +267,7 @@ static struct i2c_driver pismo_driver = { | |||
267 | .owner = THIS_MODULE, | 267 | .owner = THIS_MODULE, |
268 | }, | 268 | }, |
269 | .probe = pismo_probe, | 269 | .probe = pismo_probe, |
270 | .remove = __devexit_p(pismo_remove), | 270 | .remove = pismo_remove, |
271 | .id_table = pismo_id, | 271 | .id_table = pismo_id, |
272 | }; | 272 | }; |
273 | 273 | ||
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 81884c277405..43e3dbb976d9 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c | |||
@@ -49,7 +49,7 @@ struct pxa2xx_flash_info { | |||
49 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; | 49 | static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; |
50 | 50 | ||
51 | 51 | ||
52 | static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) | 52 | static int pxa2xx_flash_probe(struct platform_device *pdev) |
53 | { | 53 | { |
54 | struct flash_platform_data *flash = pdev->dev.platform_data; | 54 | struct flash_platform_data *flash = pdev->dev.platform_data; |
55 | struct pxa2xx_flash_info *info; | 55 | struct pxa2xx_flash_info *info; |
@@ -105,7 +105,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev) | |||
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | 107 | ||
108 | static int __devexit pxa2xx_flash_remove(struct platform_device *dev) | 108 | static int pxa2xx_flash_remove(struct platform_device *dev) |
109 | { | 109 | { |
110 | struct pxa2xx_flash_info *info = platform_get_drvdata(dev); | 110 | struct pxa2xx_flash_info *info = platform_get_drvdata(dev); |
111 | 111 | ||
@@ -139,7 +139,7 @@ static struct platform_driver pxa2xx_flash_driver = { | |||
139 | .owner = THIS_MODULE, | 139 | .owner = THIS_MODULE, |
140 | }, | 140 | }, |
141 | .probe = pxa2xx_flash_probe, | 141 | .probe = pxa2xx_flash_probe, |
142 | .remove = __devexit_p(pxa2xx_flash_remove), | 142 | .remove = pxa2xx_flash_remove, |
143 | .shutdown = pxa2xx_flash_shutdown, | 143 | .shutdown = pxa2xx_flash_shutdown, |
144 | }; | 144 | }; |
145 | 145 | ||
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index a675bdbcb0fe..f694417cf7e6 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c | |||
@@ -149,8 +149,8 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla | |||
149 | plat->exit(); | 149 | plat->exit(); |
150 | } | 150 | } |
151 | 151 | ||
152 | static struct sa_info *__devinit | 152 | static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev, |
153 | sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat) | 153 | struct flash_platform_data *plat) |
154 | { | 154 | { |
155 | struct sa_info *info; | 155 | struct sa_info *info; |
156 | int nr, size, i, ret = 0; | 156 | int nr, size, i, ret = 0; |
@@ -246,7 +246,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat) | |||
246 | 246 | ||
247 | static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; | 247 | static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; |
248 | 248 | ||
249 | static int __devinit sa1100_mtd_probe(struct platform_device *pdev) | 249 | static int sa1100_mtd_probe(struct platform_device *pdev) |
250 | { | 250 | { |
251 | struct flash_platform_data *plat = pdev->dev.platform_data; | 251 | struct flash_platform_data *plat = pdev->dev.platform_data; |
252 | struct sa_info *info; | 252 | struct sa_info *info; |
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index 9dcbc684abdb..71796137e97b 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c | |||
@@ -69,7 +69,7 @@ static struct map_info scb2_map = { | |||
69 | }; | 69 | }; |
70 | static int region_fail; | 70 | static int region_fail; |
71 | 71 | ||
72 | static int __devinit | 72 | static int |
73 | scb2_fixup_mtd(struct mtd_info *mtd) | 73 | scb2_fixup_mtd(struct mtd_info *mtd) |
74 | { | 74 | { |
75 | int i; | 75 | int i; |
@@ -133,7 +133,7 @@ scb2_fixup_mtd(struct mtd_info *mtd) | |||
133 | /* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */ | 133 | /* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */ |
134 | #define CSB5_FCR 0x41 | 134 | #define CSB5_FCR 0x41 |
135 | #define CSB5_FCR_DECODE_ALL 0x0e | 135 | #define CSB5_FCR_DECODE_ALL 0x0e |
136 | static int __devinit | 136 | static int |
137 | scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) | 137 | scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) |
138 | { | 138 | { |
139 | u8 reg; | 139 | u8 reg; |
@@ -197,7 +197,7 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | static void __devexit | 200 | static void |
201 | scb2_flash_remove(struct pci_dev *dev) | 201 | scb2_flash_remove(struct pci_dev *dev) |
202 | { | 202 | { |
203 | if (!scb2_mtd) | 203 | if (!scb2_mtd) |
@@ -231,7 +231,7 @@ static struct pci_driver scb2_flash_driver = { | |||
231 | .name = "Intel SCB2 BIOS Flash", | 231 | .name = "Intel SCB2 BIOS Flash", |
232 | .id_table = scb2_flash_pci_ids, | 232 | .id_table = scb2_flash_pci_ids, |
233 | .probe = scb2_flash_probe, | 233 | .probe = scb2_flash_probe, |
234 | .remove = __devexit_p(scb2_flash_remove), | 234 | .remove = scb2_flash_remove, |
235 | }; | 235 | }; |
236 | 236 | ||
237 | module_pci_driver(scb2_flash_driver); | 237 | module_pci_driver(scb2_flash_driver); |
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 175e537b444f..d467f3b11c96 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
@@ -108,7 +108,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp) | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int __devinit uflash_probe(struct platform_device *op) | 111 | static int uflash_probe(struct platform_device *op) |
112 | { | 112 | { |
113 | struct device_node *dp = op->dev.of_node; | 113 | struct device_node *dp = op->dev.of_node; |
114 | 114 | ||
@@ -121,7 +121,7 @@ static int __devinit uflash_probe(struct platform_device *op) | |||
121 | return uflash_devinit(op, dp); | 121 | return uflash_devinit(op, dp); |
122 | } | 122 | } |
123 | 123 | ||
124 | static int __devexit uflash_remove(struct platform_device *op) | 124 | static int uflash_remove(struct platform_device *op) |
125 | { | 125 | { |
126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); | 126 | struct uflash_dev *up = dev_get_drvdata(&op->dev); |
127 | 127 | ||
@@ -155,7 +155,7 @@ static struct platform_driver uflash_driver = { | |||
155 | .of_match_table = uflash_match, | 155 | .of_match_table = uflash_match, |
156 | }, | 156 | }, |
157 | .probe = uflash_probe, | 157 | .probe = uflash_probe, |
158 | .remove = __devexit_p(uflash_remove), | 158 | .remove = uflash_remove, |
159 | }; | 159 | }; |
160 | 160 | ||
161 | module_platform_driver(uflash_driver); | 161 | module_platform_driver(uflash_driver); |
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c index 2e2b0945edc7..6b223cfe92b7 100644 --- a/drivers/mtd/maps/vmu-flash.c +++ b/drivers/mtd/maps/vmu-flash.c | |||
@@ -596,7 +596,7 @@ fail_name: | |||
596 | } | 596 | } |
597 | 597 | ||
598 | /* Handles very basic info about the flash, queries for details */ | 598 | /* Handles very basic info about the flash, queries for details */ |
599 | static int __devinit vmu_connect(struct maple_device *mdev) | 599 | static int vmu_connect(struct maple_device *mdev) |
600 | { | 600 | { |
601 | unsigned long test_flash_data, basic_flash_data; | 601 | unsigned long test_flash_data, basic_flash_data; |
602 | int c, error; | 602 | int c, error; |
@@ -690,7 +690,7 @@ fail_nomem: | |||
690 | return error; | 690 | return error; |
691 | } | 691 | } |
692 | 692 | ||
693 | static void __devexit vmu_disconnect(struct maple_device *mdev) | 693 | static void vmu_disconnect(struct maple_device *mdev) |
694 | { | 694 | { |
695 | struct memcard *card; | 695 | struct memcard *card; |
696 | struct mdev_part *mpart; | 696 | struct mdev_part *mpart; |
@@ -772,7 +772,7 @@ static void vmu_file_error(struct maple_device *mdev, void *recvbuf) | |||
772 | } | 772 | } |
773 | 773 | ||
774 | 774 | ||
775 | static int __devinit probe_maple_vmu(struct device *dev) | 775 | static int probe_maple_vmu(struct device *dev) |
776 | { | 776 | { |
777 | int error; | 777 | int error; |
778 | struct maple_device *mdev = to_maple_dev(dev); | 778 | struct maple_device *mdev = to_maple_dev(dev); |
@@ -789,7 +789,7 @@ static int __devinit probe_maple_vmu(struct device *dev) | |||
789 | return 0; | 789 | return 0; |
790 | } | 790 | } |
791 | 791 | ||
792 | static int __devexit remove_maple_vmu(struct device *dev) | 792 | static int remove_maple_vmu(struct device *dev) |
793 | { | 793 | { |
794 | struct maple_device *mdev = to_maple_dev(dev); | 794 | struct maple_device *mdev = to_maple_dev(dev); |
795 | 795 | ||
@@ -802,7 +802,7 @@ static struct maple_driver vmu_flash_driver = { | |||
802 | .drv = { | 802 | .drv = { |
803 | .name = "Dreamcast_visual_memory", | 803 | .name = "Dreamcast_visual_memory", |
804 | .probe = probe_maple_vmu, | 804 | .probe = probe_maple_vmu, |
805 | .remove = __devexit_p(remove_maple_vmu), | 805 | .remove = remove_maple_vmu, |
806 | }, | 806 | }, |
807 | }; | 807 | }; |
808 | 808 | ||
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index f1f06715d4e0..5ad39bb5ab4c 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/hdreg.h> | 32 | #include <linux/hdreg.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | #include <linux/kthread.h> | ||
36 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
37 | 36 | ||
38 | #include "mtdcore.h" | 37 | #include "mtdcore.h" |
@@ -121,16 +120,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, | |||
121 | 120 | ||
122 | int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev) | 121 | int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev) |
123 | { | 122 | { |
124 | if (kthread_should_stop()) | ||
125 | return 1; | ||
126 | |||
127 | return dev->bg_stop; | 123 | return dev->bg_stop; |
128 | } | 124 | } |
129 | EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background); | 125 | EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background); |
130 | 126 | ||
131 | static int mtd_blktrans_thread(void *arg) | 127 | static void mtd_blktrans_work(struct work_struct *work) |
132 | { | 128 | { |
133 | struct mtd_blktrans_dev *dev = arg; | 129 | struct mtd_blktrans_dev *dev = |
130 | container_of(work, struct mtd_blktrans_dev, work); | ||
134 | struct mtd_blktrans_ops *tr = dev->tr; | 131 | struct mtd_blktrans_ops *tr = dev->tr; |
135 | struct request_queue *rq = dev->rq; | 132 | struct request_queue *rq = dev->rq; |
136 | struct request *req = NULL; | 133 | struct request *req = NULL; |
@@ -138,7 +135,7 @@ static int mtd_blktrans_thread(void *arg) | |||
138 | 135 | ||
139 | spin_lock_irq(rq->queue_lock); | 136 | spin_lock_irq(rq->queue_lock); |
140 | 137 | ||
141 | while (!kthread_should_stop()) { | 138 | while (1) { |
142 | int res; | 139 | int res; |
143 | 140 | ||
144 | dev->bg_stop = false; | 141 | dev->bg_stop = false; |
@@ -156,15 +153,7 @@ static int mtd_blktrans_thread(void *arg) | |||
156 | background_done = !dev->bg_stop; | 153 | background_done = !dev->bg_stop; |
157 | continue; | 154 | continue; |
158 | } | 155 | } |
159 | set_current_state(TASK_INTERRUPTIBLE); | 156 | break; |
160 | |||
161 | if (kthread_should_stop()) | ||
162 | set_current_state(TASK_RUNNING); | ||
163 | |||
164 | spin_unlock_irq(rq->queue_lock); | ||
165 | schedule(); | ||
166 | spin_lock_irq(rq->queue_lock); | ||
167 | continue; | ||
168 | } | 157 | } |
169 | 158 | ||
170 | spin_unlock_irq(rq->queue_lock); | 159 | spin_unlock_irq(rq->queue_lock); |
@@ -185,8 +174,6 @@ static int mtd_blktrans_thread(void *arg) | |||
185 | __blk_end_request_all(req, -EIO); | 174 | __blk_end_request_all(req, -EIO); |
186 | 175 | ||
187 | spin_unlock_irq(rq->queue_lock); | 176 | spin_unlock_irq(rq->queue_lock); |
188 | |||
189 | return 0; | ||
190 | } | 177 | } |
191 | 178 | ||
192 | static void mtd_blktrans_request(struct request_queue *rq) | 179 | static void mtd_blktrans_request(struct request_queue *rq) |
@@ -199,10 +186,8 @@ static void mtd_blktrans_request(struct request_queue *rq) | |||
199 | if (!dev) | 186 | if (!dev) |
200 | while ((req = blk_fetch_request(rq)) != NULL) | 187 | while ((req = blk_fetch_request(rq)) != NULL) |
201 | __blk_end_request_all(req, -ENODEV); | 188 | __blk_end_request_all(req, -ENODEV); |
202 | else { | 189 | else |
203 | dev->bg_stop = true; | 190 | queue_work(dev->wq, &dev->work); |
204 | wake_up_process(dev->thread); | ||
205 | } | ||
206 | } | 191 | } |
207 | 192 | ||
208 | static int blktrans_open(struct block_device *bdev, fmode_t mode) | 193 | static int blktrans_open(struct block_device *bdev, fmode_t mode) |
@@ -325,7 +310,7 @@ unlock: | |||
325 | return ret; | 310 | return ret; |
326 | } | 311 | } |
327 | 312 | ||
328 | static const struct block_device_operations mtd_blktrans_ops = { | 313 | static const struct block_device_operations mtd_block_ops = { |
329 | .owner = THIS_MODULE, | 314 | .owner = THIS_MODULE, |
330 | .open = blktrans_open, | 315 | .open = blktrans_open, |
331 | .release = blktrans_release, | 316 | .release = blktrans_release, |
@@ -401,7 +386,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
401 | gd->private_data = new; | 386 | gd->private_data = new; |
402 | gd->major = tr->major; | 387 | gd->major = tr->major; |
403 | gd->first_minor = (new->devnum) << tr->part_bits; | 388 | gd->first_minor = (new->devnum) << tr->part_bits; |
404 | gd->fops = &mtd_blktrans_ops; | 389 | gd->fops = &mtd_block_ops; |
405 | 390 | ||
406 | if (tr->part_bits) | 391 | if (tr->part_bits) |
407 | if (new->devnum < 26) | 392 | if (new->devnum < 26) |
@@ -437,14 +422,13 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
437 | 422 | ||
438 | gd->queue = new->rq; | 423 | gd->queue = new->rq; |
439 | 424 | ||
440 | /* Create processing thread */ | 425 | /* Create processing workqueue */ |
441 | /* TODO: workqueue ? */ | 426 | new->wq = alloc_workqueue("%s%d", 0, 0, |
442 | new->thread = kthread_run(mtd_blktrans_thread, new, | 427 | tr->name, new->mtd->index); |
443 | "%s%d", tr->name, new->mtd->index); | 428 | if (!new->wq) |
444 | if (IS_ERR(new->thread)) { | ||
445 | ret = PTR_ERR(new->thread); | ||
446 | goto error4; | 429 | goto error4; |
447 | } | 430 | INIT_WORK(&new->work, mtd_blktrans_work); |
431 | |||
448 | gd->driverfs_dev = &new->mtd->dev; | 432 | gd->driverfs_dev = &new->mtd->dev; |
449 | 433 | ||
450 | if (new->readonly) | 434 | if (new->readonly) |
@@ -484,9 +468,8 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) | |||
484 | /* Stop new requests to arrive */ | 468 | /* Stop new requests to arrive */ |
485 | del_gendisk(old->disk); | 469 | del_gendisk(old->disk); |
486 | 470 | ||
487 | 471 | /* Stop workqueue. This will perform any pending request. */ | |
488 | /* Stop the thread */ | 472 | destroy_workqueue(old->wq); |
489 | kthread_stop(old->thread); | ||
490 | 473 | ||
491 | /* Kill current requests */ | 474 | /* Kill current requests */ |
492 | spin_lock_irqsave(&old->queue_lock, flags); | 475 | spin_lock_irqsave(&old->queue_lock, flags); |
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index f5b3f91fa1cc..97bb8f6304d4 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c | |||
@@ -271,7 +271,7 @@ static void find_next_position(struct mtdoops_context *cxt) | |||
271 | 271 | ||
272 | if (count[0] == 0xffffffff && count[1] == 0xffffffff) | 272 | if (count[0] == 0xffffffff && count[1] == 0xffffffff) |
273 | mark_page_unused(cxt, page); | 273 | mark_page_unused(cxt, page); |
274 | if (count[0] == 0xffffffff) | 274 | if (count[0] == 0xffffffff || count[1] != MTDOOPS_KERNMSG_MAGIC) |
275 | continue; | 275 | continue; |
276 | if (maxcount == 0xffffffff) { | 276 | if (maxcount == 0xffffffff) { |
277 | maxcount = count[0]; | 277 | maxcount = count[0]; |
@@ -289,14 +289,13 @@ static void find_next_position(struct mtdoops_context *cxt) | |||
289 | } | 289 | } |
290 | } | 290 | } |
291 | if (maxcount == 0xffffffff) { | 291 | if (maxcount == 0xffffffff) { |
292 | cxt->nextpage = 0; | 292 | cxt->nextpage = cxt->oops_pages - 1; |
293 | cxt->nextcount = 1; | 293 | cxt->nextcount = 0; |
294 | schedule_work(&cxt->work_erase); | 294 | } |
295 | return; | 295 | else { |
296 | cxt->nextpage = maxpos; | ||
297 | cxt->nextcount = maxcount; | ||
296 | } | 298 | } |
297 | |||
298 | cxt->nextpage = maxpos; | ||
299 | cxt->nextcount = maxcount; | ||
300 | 299 | ||
301 | mtdoops_inc_counter(cxt); | 300 | mtdoops_inc_counter(cxt); |
302 | } | 301 | } |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index dae191b3c081..5819eb575210 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -50,16 +50,30 @@ config MTD_NAND_MUSEUM_IDS | |||
50 | of these chips were reused by later, larger chips. | 50 | of these chips were reused by later, larger chips. |
51 | 51 | ||
52 | config MTD_NAND_DENALI | 52 | config MTD_NAND_DENALI |
53 | depends on PCI | 53 | tristate "Support Denali NAND controller" |
54 | help | ||
55 | Enable support for the Denali NAND controller. This should be | ||
56 | combined with either the PCI or platform drivers to provide device | ||
57 | registration. | ||
58 | |||
59 | config MTD_NAND_DENALI_PCI | ||
54 | tristate "Support Denali NAND controller on Intel Moorestown" | 60 | tristate "Support Denali NAND controller on Intel Moorestown" |
61 | depends on PCI && MTD_NAND_DENALI | ||
55 | help | 62 | help |
56 | Enable the driver for NAND flash on Intel Moorestown, using the | 63 | Enable the driver for NAND flash on Intel Moorestown, using the |
57 | Denali NAND controller core. | 64 | Denali NAND controller core. |
58 | 65 | ||
66 | config MTD_NAND_DENALI_DT | ||
67 | tristate "Support Denali NAND controller as a DT device" | ||
68 | depends on HAVE_CLK && MTD_NAND_DENALI | ||
69 | help | ||
70 | Enable the driver for NAND flash on platforms using a Denali NAND | ||
71 | controller as a DT device. | ||
72 | |||
59 | config MTD_NAND_DENALI_SCRATCH_REG_ADDR | 73 | config MTD_NAND_DENALI_SCRATCH_REG_ADDR |
60 | hex "Denali NAND size scratch register address" | 74 | hex "Denali NAND size scratch register address" |
61 | default "0xFF108018" | 75 | default "0xFF108018" |
62 | depends on MTD_NAND_DENALI | 76 | depends on MTD_NAND_DENALI_PCI |
63 | help | 77 | help |
64 | Some platforms place the NAND chip size in a scratch register | 78 | Some platforms place the NAND chip size in a scratch register |
65 | because (some versions of) the driver aren't able to automatically | 79 | because (some versions of) the driver aren't able to automatically |
@@ -433,6 +447,14 @@ config MTD_NAND_GPMI_NAND | |||
433 | block, such as SD card. So pay attention to it when you enable | 447 | block, such as SD card. So pay attention to it when you enable |
434 | the GPMI. | 448 | the GPMI. |
435 | 449 | ||
450 | config MTD_NAND_BCM47XXNFLASH | ||
451 | tristate "Support for NAND flash on BCM4706 BCMA bus" | ||
452 | depends on BCMA_NFLASH | ||
453 | help | ||
454 | BCMA bus can have various flash memories attached, they are | ||
455 | registered by bcma as platform devices. This enables driver for | ||
456 | NAND flash memories. For now only BCM4706 is supported. | ||
457 | |||
436 | config MTD_NAND_PLATFORM | 458 | config MTD_NAND_PLATFORM |
437 | tristate "Support for generic platform NAND driver" | 459 | tristate "Support for generic platform NAND driver" |
438 | depends on HAS_IOMEM | 460 | depends on HAS_IOMEM |
@@ -499,12 +521,6 @@ config MTD_NAND_MXC | |||
499 | This enables the driver for the NAND flash controller on the | 521 | This enables the driver for the NAND flash controller on the |
500 | MXC processors. | 522 | MXC processors. |
501 | 523 | ||
502 | config MTD_NAND_NOMADIK | ||
503 | tristate "ST Nomadik 8815 NAND support" | ||
504 | depends on ARCH_NOMADIK | ||
505 | help | ||
506 | Driver for the NAND flash controller on the Nomadik, with ECC. | ||
507 | |||
508 | config MTD_NAND_SH_FLCTL | 524 | config MTD_NAND_SH_FLCTL |
509 | tristate "Support for NAND on Renesas SuperH FLCTL" | 525 | tristate "Support for NAND on Renesas SuperH FLCTL" |
510 | depends on SUPERH || ARCH_SHMOBILE | 526 | depends on SUPERH || ARCH_SHMOBILE |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 6c7f2b3ca8ae..d76d91205691 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -11,6 +11,8 @@ obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o | |||
11 | obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o | 11 | obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o |
12 | obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o | 12 | obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o |
13 | obj-$(CONFIG_MTD_NAND_DENALI) += denali.o | 13 | obj-$(CONFIG_MTD_NAND_DENALI) += denali.o |
14 | obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o | ||
15 | obj-$(CONFIG_MTD_NAND_DENALI_DT) += denali_dt.o | ||
14 | obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o | 16 | obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o |
15 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o | 17 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o |
16 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o | 18 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o |
@@ -45,11 +47,11 @@ obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o | |||
45 | obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o | 47 | obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o |
46 | obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o | 48 | obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o |
47 | obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o | 49 | obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o |
48 | obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o | ||
49 | obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o | 50 | obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o |
50 | obj-$(CONFIG_MTD_NAND_RICOH) += r852.o | 51 | obj-$(CONFIG_MTD_NAND_RICOH) += r852.o |
51 | obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o | 52 | obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o |
52 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ | 53 | obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ |
53 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o | 54 | obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o |
55 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ | ||
54 | 56 | ||
55 | nand-objs := nand_base.o nand_bbt.o | 57 | nand-objs := nand_base.o nand_bbt.o |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 9e7723aa7acc..f1d71cdc8aac 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -173,7 +173,7 @@ static const struct gpio _mandatory_gpio[] = { | |||
173 | /* | 173 | /* |
174 | * Main initialization routine | 174 | * Main initialization routine |
175 | */ | 175 | */ |
176 | static int __devinit ams_delta_init(struct platform_device *pdev) | 176 | static int ams_delta_init(struct platform_device *pdev) |
177 | { | 177 | { |
178 | struct nand_chip *this; | 178 | struct nand_chip *this; |
179 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 179 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -270,7 +270,7 @@ out_free: | |||
270 | /* | 270 | /* |
271 | * Clean up routine | 271 | * Clean up routine |
272 | */ | 272 | */ |
273 | static int __devexit ams_delta_cleanup(struct platform_device *pdev) | 273 | static int ams_delta_cleanup(struct platform_device *pdev) |
274 | { | 274 | { |
275 | void __iomem *io_base = platform_get_drvdata(pdev); | 275 | void __iomem *io_base = platform_get_drvdata(pdev); |
276 | 276 | ||
@@ -289,7 +289,7 @@ static int __devexit ams_delta_cleanup(struct platform_device *pdev) | |||
289 | 289 | ||
290 | static struct platform_driver ams_delta_nand_driver = { | 290 | static struct platform_driver ams_delta_nand_driver = { |
291 | .probe = ams_delta_init, | 291 | .probe = ams_delta_init, |
292 | .remove = __devexit_p(ams_delta_cleanup), | 292 | .remove = ams_delta_cleanup, |
293 | .driver = { | 293 | .driver = { |
294 | .name = "ams-delta-nand", | 294 | .name = "ams-delta-nand", |
295 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 92623ac2015a..90bdca61c797 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -331,13 +331,13 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
331 | * 12-bits 20-bytes 21-bytes | 331 | * 12-bits 20-bytes 21-bytes |
332 | * 24-bits 39-bytes 42-bytes | 332 | * 24-bits 39-bytes 42-bytes |
333 | */ | 333 | */ |
334 | static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size) | 334 | static int pmecc_get_ecc_bytes(int cap, int sector_size) |
335 | { | 335 | { |
336 | int m = 12 + sector_size / 512; | 336 | int m = 12 + sector_size / 512; |
337 | return (m * cap + 7) / 8; | 337 | return (m * cap + 7) / 8; |
338 | } | 338 | } |
339 | 339 | ||
340 | static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, | 340 | static void pmecc_config_ecc_layout(struct nand_ecclayout *layout, |
341 | int oobsize, int ecc_len) | 341 | int oobsize, int ecc_len) |
342 | { | 342 | { |
343 | int i; | 343 | int i; |
@@ -353,7 +353,7 @@ static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, | |||
353 | oobsize - ecc_len - layout->oobfree[0].offset; | 353 | oobsize - ecc_len - layout->oobfree[0].offset; |
354 | } | 354 | } |
355 | 355 | ||
356 | static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) | 356 | static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) |
357 | { | 357 | { |
358 | int table_size; | 358 | int table_size; |
359 | 359 | ||
@@ -375,7 +375,7 @@ static void pmecc_data_free(struct atmel_nand_host *host) | |||
375 | kfree(host->pmecc_delta); | 375 | kfree(host->pmecc_delta); |
376 | } | 376 | } |
377 | 377 | ||
378 | static int __devinit pmecc_data_alloc(struct atmel_nand_host *host) | 378 | static int pmecc_data_alloc(struct atmel_nand_host *host) |
379 | { | 379 | { |
380 | const int cap = host->pmecc_corr_cap; | 380 | const int cap = host->pmecc_corr_cap; |
381 | 381 | ||
@@ -724,6 +724,7 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, | |||
724 | struct atmel_nand_host *host = nand_chip->priv; | 724 | struct atmel_nand_host *host = nand_chip->priv; |
725 | int i, err_nbr, eccbytes; | 725 | int i, err_nbr, eccbytes; |
726 | uint8_t *buf_pos; | 726 | uint8_t *buf_pos; |
727 | int total_err = 0; | ||
727 | 728 | ||
728 | eccbytes = nand_chip->ecc.bytes; | 729 | eccbytes = nand_chip->ecc.bytes; |
729 | for (i = 0; i < eccbytes; i++) | 730 | for (i = 0; i < eccbytes; i++) |
@@ -751,12 +752,13 @@ normal_check: | |||
751 | pmecc_correct_data(mtd, buf_pos, ecc, i, | 752 | pmecc_correct_data(mtd, buf_pos, ecc, i, |
752 | host->pmecc_bytes_per_sector, err_nbr); | 753 | host->pmecc_bytes_per_sector, err_nbr); |
753 | mtd->ecc_stats.corrected += err_nbr; | 754 | mtd->ecc_stats.corrected += err_nbr; |
755 | total_err += err_nbr; | ||
754 | } | 756 | } |
755 | } | 757 | } |
756 | pmecc_stat >>= 1; | 758 | pmecc_stat >>= 1; |
757 | } | 759 | } |
758 | 760 | ||
759 | return 0; | 761 | return total_err; |
760 | } | 762 | } |
761 | 763 | ||
762 | static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | 764 | static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, |
@@ -768,6 +770,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
768 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 770 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
769 | uint32_t stat; | 771 | uint32_t stat; |
770 | unsigned long end_time; | 772 | unsigned long end_time; |
773 | int bitflips = 0; | ||
771 | 774 | ||
772 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | 775 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); |
773 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | 776 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); |
@@ -790,11 +793,14 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
790 | } | 793 | } |
791 | 794 | ||
792 | stat = pmecc_readl_relaxed(host->ecc, ISR); | 795 | stat = pmecc_readl_relaxed(host->ecc, ISR); |
793 | if (stat != 0) | 796 | if (stat != 0) { |
794 | if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0) | 797 | bitflips = pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]); |
795 | return -EIO; | 798 | if (bitflips < 0) |
799 | /* uncorrectable errors */ | ||
800 | return 0; | ||
801 | } | ||
796 | 802 | ||
797 | return 0; | 803 | return bitflips; |
798 | } | 804 | } |
799 | 805 | ||
800 | static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, | 806 | static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, |
@@ -1206,7 +1212,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
1206 | } | 1212 | } |
1207 | 1213 | ||
1208 | #if defined(CONFIG_OF) | 1214 | #if defined(CONFIG_OF) |
1209 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | 1215 | static int atmel_of_init_port(struct atmel_nand_host *host, |
1210 | struct device_node *np) | 1216 | struct device_node *np) |
1211 | { | 1217 | { |
1212 | u32 val, table_offset; | 1218 | u32 val, table_offset; |
@@ -1293,7 +1299,7 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | |||
1293 | return 0; | 1299 | return 0; |
1294 | } | 1300 | } |
1295 | #else | 1301 | #else |
1296 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | 1302 | static int atmel_of_init_port(struct atmel_nand_host *host, |
1297 | struct device_node *np) | 1303 | struct device_node *np) |
1298 | { | 1304 | { |
1299 | return -EINVAL; | 1305 | return -EINVAL; |
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 5c47b200045a..217459d02b2f 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -382,7 +382,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i | |||
382 | while(!this->dev_ready(mtd)); | 382 | while(!this->dev_ready(mtd)); |
383 | } | 383 | } |
384 | 384 | ||
385 | static int __devinit find_nand_cs(unsigned long nand_base) | 385 | static int find_nand_cs(unsigned long nand_base) |
386 | { | 386 | { |
387 | void __iomem *base = | 387 | void __iomem *base = |
388 | (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR); | 388 | (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR); |
@@ -403,7 +403,7 @@ static int __devinit find_nand_cs(unsigned long nand_base) | |||
403 | return -ENODEV; | 403 | return -ENODEV; |
404 | } | 404 | } |
405 | 405 | ||
406 | static int __devinit au1550nd_probe(struct platform_device *pdev) | 406 | static int au1550nd_probe(struct platform_device *pdev) |
407 | { | 407 | { |
408 | struct au1550nd_platdata *pd; | 408 | struct au1550nd_platdata *pd; |
409 | struct au1550nd_ctx *ctx; | 409 | struct au1550nd_ctx *ctx; |
@@ -491,7 +491,7 @@ out1: | |||
491 | return ret; | 491 | return ret; |
492 | } | 492 | } |
493 | 493 | ||
494 | static int __devexit au1550nd_remove(struct platform_device *pdev) | 494 | static int au1550nd_remove(struct platform_device *pdev) |
495 | { | 495 | { |
496 | struct au1550nd_ctx *ctx = platform_get_drvdata(pdev); | 496 | struct au1550nd_ctx *ctx = platform_get_drvdata(pdev); |
497 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 497 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -509,7 +509,7 @@ static struct platform_driver au1550nd_driver = { | |||
509 | .owner = THIS_MODULE, | 509 | .owner = THIS_MODULE, |
510 | }, | 510 | }, |
511 | .probe = au1550nd_probe, | 511 | .probe = au1550nd_probe, |
512 | .remove = __devexit_p(au1550nd_remove), | 512 | .remove = au1550nd_remove, |
513 | }; | 513 | }; |
514 | 514 | ||
515 | module_platform_driver(au1550nd_driver); | 515 | module_platform_driver(au1550nd_driver); |
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile new file mode 100644 index 000000000000..f05b119e134b --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | bcm47xxnflash-y += main.o | ||
2 | bcm47xxnflash-y += ops_bcm4706.o | ||
3 | |||
4 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o | ||
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h new file mode 100644 index 000000000000..0bdb2ce4da75 --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef __BCM47XXNFLASH_H | ||
2 | #define __BCM47XXNFLASH_H | ||
3 | |||
4 | #include <linux/mtd/mtd.h> | ||
5 | #include <linux/mtd/nand.h> | ||
6 | |||
7 | struct bcm47xxnflash { | ||
8 | struct bcma_drv_cc *cc; | ||
9 | |||
10 | struct nand_chip nand_chip; | ||
11 | struct mtd_info mtd; | ||
12 | |||
13 | unsigned curr_command; | ||
14 | int curr_page_addr; | ||
15 | int curr_column; | ||
16 | |||
17 | u8 id_data[8]; | ||
18 | }; | ||
19 | |||
20 | int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n); | ||
21 | |||
22 | #endif /* BCM47XXNFLASH */ | ||
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c new file mode 100644 index 000000000000..2b8b05bec3dd --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/main.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * BCM47XX NAND flash driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.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 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/bcma/bcma.h> | ||
17 | |||
18 | #include "bcm47xxnflash.h" | ||
19 | |||
20 | MODULE_DESCRIPTION("NAND flash driver for BCMA bus"); | ||
21 | MODULE_LICENSE("GPL"); | ||
22 | MODULE_AUTHOR("Rafał Miłecki"); | ||
23 | |||
24 | static const char *probes[] = { "bcm47xxpart", NULL }; | ||
25 | |||
26 | static int bcm47xxnflash_probe(struct platform_device *pdev) | ||
27 | { | ||
28 | struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev); | ||
29 | struct bcm47xxnflash *b47n; | ||
30 | int err = 0; | ||
31 | |||
32 | b47n = kzalloc(sizeof(*b47n), GFP_KERNEL); | ||
33 | if (!b47n) { | ||
34 | err = -ENOMEM; | ||
35 | goto out; | ||
36 | } | ||
37 | |||
38 | b47n->nand_chip.priv = b47n; | ||
39 | b47n->mtd.owner = THIS_MODULE; | ||
40 | b47n->mtd.priv = &b47n->nand_chip; /* Required */ | ||
41 | b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash); | ||
42 | |||
43 | if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | ||
44 | err = bcm47xxnflash_ops_bcm4706_init(b47n); | ||
45 | } else { | ||
46 | pr_err("Device not supported\n"); | ||
47 | err = -ENOTSUPP; | ||
48 | } | ||
49 | if (err) { | ||
50 | pr_err("Initialization failed: %d\n", err); | ||
51 | goto err_init; | ||
52 | } | ||
53 | |||
54 | err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0); | ||
55 | if (err) { | ||
56 | pr_err("Failed to register MTD device: %d\n", err); | ||
57 | goto err_dev_reg; | ||
58 | } | ||
59 | |||
60 | return 0; | ||
61 | |||
62 | err_dev_reg: | ||
63 | err_init: | ||
64 | kfree(b47n); | ||
65 | out: | ||
66 | return err; | ||
67 | } | ||
68 | |||
69 | static int __devexit bcm47xxnflash_remove(struct platform_device *pdev) | ||
70 | { | ||
71 | struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev); | ||
72 | |||
73 | if (nflash->mtd) | ||
74 | mtd_device_unregister(nflash->mtd); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static struct platform_driver bcm47xxnflash_driver = { | ||
80 | .remove = __devexit_p(bcm47xxnflash_remove), | ||
81 | .driver = { | ||
82 | .name = "bcma_nflash", | ||
83 | .owner = THIS_MODULE, | ||
84 | }, | ||
85 | }; | ||
86 | |||
87 | static int __init bcm47xxnflash_init(void) | ||
88 | { | ||
89 | int err; | ||
90 | |||
91 | /* | ||
92 | * Platform device "bcma_nflash" exists on SoCs and is registered very | ||
93 | * early, it won't be added during runtime (use platform_driver_probe). | ||
94 | */ | ||
95 | err = platform_driver_probe(&bcm47xxnflash_driver, bcm47xxnflash_probe); | ||
96 | if (err) | ||
97 | pr_err("Failed to register serial flash driver: %d\n", err); | ||
98 | |||
99 | return err; | ||
100 | } | ||
101 | |||
102 | static void __exit bcm47xxnflash_exit(void) | ||
103 | { | ||
104 | platform_driver_unregister(&bcm47xxnflash_driver); | ||
105 | } | ||
106 | |||
107 | module_init(bcm47xxnflash_init); | ||
108 | module_exit(bcm47xxnflash_exit); | ||
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c new file mode 100644 index 000000000000..86c9a79b89b3 --- /dev/null +++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | |||
@@ -0,0 +1,413 @@ | |||
1 | /* | ||
2 | * BCM47XX NAND flash driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.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 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/bcma/bcma.h> | ||
16 | |||
17 | #include "bcm47xxnflash.h" | ||
18 | |||
19 | /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has | ||
20 | * shown 164 retries as maxiumum. */ | ||
21 | #define NFLASH_READY_RETRIES 1000 | ||
22 | |||
23 | #define NFLASH_SECTOR_SIZE 512 | ||
24 | |||
25 | #define NCTL_CMD0 0x00010000 | ||
26 | #define NCTL_CMD1W 0x00080000 | ||
27 | #define NCTL_READ 0x00100000 | ||
28 | #define NCTL_WRITE 0x00200000 | ||
29 | #define NCTL_SPECADDR 0x01000000 | ||
30 | #define NCTL_READY 0x04000000 | ||
31 | #define NCTL_ERR 0x08000000 | ||
32 | #define NCTL_CSA 0x40000000 | ||
33 | #define NCTL_START 0x80000000 | ||
34 | |||
35 | /************************************************** | ||
36 | * Various helpers | ||
37 | **************************************************/ | ||
38 | |||
39 | static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock) | ||
40 | { | ||
41 | return ((ns * 1000 * clock) / 1000000) + 1; | ||
42 | } | ||
43 | |||
44 | static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code) | ||
45 | { | ||
46 | int i = 0; | ||
47 | |||
48 | bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code); | ||
49 | for (i = 0; i < NFLASH_READY_RETRIES; i++) { | ||
50 | if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) { | ||
51 | i = 0; | ||
52 | break; | ||
53 | } | ||
54 | } | ||
55 | if (i) { | ||
56 | pr_err("NFLASH control command not ready!\n"); | ||
57 | return -EBUSY; | ||
58 | } | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc) | ||
63 | { | ||
64 | int i; | ||
65 | |||
66 | for (i = 0; i < NFLASH_READY_RETRIES; i++) { | ||
67 | if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) { | ||
68 | if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & | ||
69 | BCMA_CC_NFLASH_CTL_ERR) { | ||
70 | pr_err("Error on polling\n"); | ||
71 | return -EBUSY; | ||
72 | } else { | ||
73 | return 0; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | |||
78 | pr_err("Polling timeout!\n"); | ||
79 | return -EBUSY; | ||
80 | } | ||
81 | |||
82 | /************************************************** | ||
83 | * R/W | ||
84 | **************************************************/ | ||
85 | |||
86 | static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf, | ||
87 | int len) | ||
88 | { | ||
89 | struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; | ||
90 | struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; | ||
91 | |||
92 | u32 ctlcode; | ||
93 | u32 *dest = (u32 *)buf; | ||
94 | int i; | ||
95 | int toread; | ||
96 | |||
97 | BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask); | ||
98 | /* Don't validate column using nand_chip->page_shift, it may be bigger | ||
99 | * when accessing OOB */ | ||
100 | |||
101 | while (len) { | ||
102 | /* We can read maximum of 0x200 bytes at once */ | ||
103 | toread = min(len, 0x200); | ||
104 | |||
105 | /* Set page and column */ | ||
106 | bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR, | ||
107 | b47n->curr_column); | ||
108 | bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR, | ||
109 | b47n->curr_page_addr); | ||
110 | |||
111 | /* Prepare to read */ | ||
112 | ctlcode = NCTL_CSA | NCTL_CMD1W | 0x00040000 | 0x00020000 | | ||
113 | NCTL_CMD0; | ||
114 | ctlcode |= NAND_CMD_READSTART << 8; | ||
115 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) | ||
116 | return; | ||
117 | if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc)) | ||
118 | return; | ||
119 | |||
120 | /* Eventually read some data :) */ | ||
121 | for (i = 0; i < toread; i += 4, dest++) { | ||
122 | ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ; | ||
123 | if (i == toread - 4) /* Last read goes without that */ | ||
124 | ctlcode &= ~NCTL_CSA; | ||
125 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, | ||
126 | ctlcode)) | ||
127 | return; | ||
128 | *dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA); | ||
129 | } | ||
130 | |||
131 | b47n->curr_column += toread; | ||
132 | len -= toread; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd, | ||
137 | const uint8_t *buf, int len) | ||
138 | { | ||
139 | struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; | ||
140 | struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; | ||
141 | struct bcma_drv_cc *cc = b47n->cc; | ||
142 | |||
143 | u32 ctlcode; | ||
144 | const u32 *data = (u32 *)buf; | ||
145 | int i; | ||
146 | |||
147 | BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask); | ||
148 | /* Don't validate column using nand_chip->page_shift, it may be bigger | ||
149 | * when accessing OOB */ | ||
150 | |||
151 | for (i = 0; i < len; i += 4, data++) { | ||
152 | bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data); | ||
153 | |||
154 | ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE; | ||
155 | if (i == len - 4) /* Last read goes without that */ | ||
156 | ctlcode &= ~NCTL_CSA; | ||
157 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) { | ||
158 | pr_err("%s ctl_cmd didn't work!\n", __func__); | ||
159 | return; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | b47n->curr_column += len; | ||
164 | } | ||
165 | |||
166 | /************************************************** | ||
167 | * NAND chip ops | ||
168 | **************************************************/ | ||
169 | |||
170 | /* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */ | ||
171 | static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd, | ||
172 | int chip) | ||
173 | { | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Default nand_command and nand_command_lp don't match BCM4706 hardware layout. | ||
179 | * For example, reading chip id is performed in a non-standard way. | ||
180 | * Setting column and page is also handled differently, we use a special | ||
181 | * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert | ||
182 | * standard commands would be much more complicated. | ||
183 | */ | ||
184 | static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, | ||
185 | unsigned command, int column, | ||
186 | int page_addr) | ||
187 | { | ||
188 | struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; | ||
189 | struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; | ||
190 | struct bcma_drv_cc *cc = b47n->cc; | ||
191 | u32 ctlcode; | ||
192 | int i; | ||
193 | |||
194 | if (column != -1) | ||
195 | b47n->curr_column = column; | ||
196 | if (page_addr != -1) | ||
197 | b47n->curr_page_addr = page_addr; | ||
198 | |||
199 | switch (command) { | ||
200 | case NAND_CMD_RESET: | ||
201 | pr_warn("Chip reset not implemented yet\n"); | ||
202 | break; | ||
203 | case NAND_CMD_READID: | ||
204 | ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0; | ||
205 | ctlcode |= NAND_CMD_READID; | ||
206 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) { | ||
207 | pr_err("READID error\n"); | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Reading is specific, last one has to go without NCTL_CSA | ||
213 | * bit. We don't know how many reads NAND subsystem is going | ||
214 | * to perform, so cache everything. | ||
215 | */ | ||
216 | for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) { | ||
217 | ctlcode = NCTL_CSA | NCTL_READ; | ||
218 | if (i == ARRAY_SIZE(b47n->id_data) - 1) | ||
219 | ctlcode &= ~NCTL_CSA; | ||
220 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, | ||
221 | ctlcode)) { | ||
222 | pr_err("READID error\n"); | ||
223 | break; | ||
224 | } | ||
225 | b47n->id_data[i] = | ||
226 | bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA) | ||
227 | & 0xFF; | ||
228 | } | ||
229 | |||
230 | break; | ||
231 | case NAND_CMD_STATUS: | ||
232 | ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS; | ||
233 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) | ||
234 | pr_err("STATUS command error\n"); | ||
235 | break; | ||
236 | case NAND_CMD_READ0: | ||
237 | break; | ||
238 | case NAND_CMD_READOOB: | ||
239 | if (page_addr != -1) | ||
240 | b47n->curr_column += mtd->writesize; | ||
241 | break; | ||
242 | case NAND_CMD_ERASE1: | ||
243 | bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR, | ||
244 | b47n->curr_page_addr); | ||
245 | ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 | | ||
246 | NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8); | ||
247 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) | ||
248 | pr_err("ERASE1 failed\n"); | ||
249 | break; | ||
250 | case NAND_CMD_ERASE2: | ||
251 | break; | ||
252 | case NAND_CMD_SEQIN: | ||
253 | /* Set page and column */ | ||
254 | bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR, | ||
255 | b47n->curr_column); | ||
256 | bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR, | ||
257 | b47n->curr_page_addr); | ||
258 | |||
259 | /* Prepare to write */ | ||
260 | ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000; | ||
261 | ctlcode |= NAND_CMD_SEQIN; | ||
262 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) | ||
263 | pr_err("SEQIN failed\n"); | ||
264 | break; | ||
265 | case NAND_CMD_PAGEPROG: | ||
266 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, 0x00010000 | | ||
267 | NAND_CMD_PAGEPROG)) | ||
268 | pr_err("PAGEPROG failed\n"); | ||
269 | if (bcm47xxnflash_ops_bcm4706_poll(cc)) | ||
270 | pr_err("PAGEPROG not ready\n"); | ||
271 | break; | ||
272 | default: | ||
273 | pr_err("Command 0x%X unsupported\n", command); | ||
274 | break; | ||
275 | } | ||
276 | b47n->curr_command = command; | ||
277 | } | ||
278 | |||
279 | static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd) | ||
280 | { | ||
281 | struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; | ||
282 | struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; | ||
283 | struct bcma_drv_cc *cc = b47n->cc; | ||
284 | u32 tmp = 0; | ||
285 | |||
286 | switch (b47n->curr_command) { | ||
287 | case NAND_CMD_READID: | ||
288 | if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) { | ||
289 | pr_err("Requested invalid id_data: %d\n", | ||
290 | b47n->curr_column); | ||
291 | return 0; | ||
292 | } | ||
293 | return b47n->id_data[b47n->curr_column++]; | ||
294 | case NAND_CMD_STATUS: | ||
295 | if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ)) | ||
296 | return 0; | ||
297 | return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff; | ||
298 | case NAND_CMD_READOOB: | ||
299 | bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4); | ||
300 | return tmp & 0xFF; | ||
301 | } | ||
302 | |||
303 | pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd, | ||
308 | uint8_t *buf, int len) | ||
309 | { | ||
310 | struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; | ||
311 | struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; | ||
312 | |||
313 | switch (b47n->curr_command) { | ||
314 | case NAND_CMD_READ0: | ||
315 | case NAND_CMD_READOOB: | ||
316 | bcm47xxnflash_ops_bcm4706_read(mtd, buf, len); | ||
317 | return; | ||
318 | } | ||
319 | |||
320 | pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command); | ||
321 | } | ||
322 | |||
323 | static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd, | ||
324 | const uint8_t *buf, int len) | ||
325 | { | ||
326 | struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv; | ||
327 | struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv; | ||
328 | |||
329 | switch (b47n->curr_command) { | ||
330 | case NAND_CMD_SEQIN: | ||
331 | bcm47xxnflash_ops_bcm4706_write(mtd, buf, len); | ||
332 | return; | ||
333 | } | ||
334 | |||
335 | pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command); | ||
336 | } | ||
337 | |||
338 | /************************************************** | ||
339 | * Init | ||
340 | **************************************************/ | ||
341 | |||
342 | int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) | ||
343 | { | ||
344 | int err; | ||
345 | u32 freq; | ||
346 | u16 clock; | ||
347 | u8 w0, w1, w2, w3, w4; | ||
348 | |||
349 | unsigned long chipsize; /* MiB */ | ||
350 | u8 tbits, col_bits, col_size, row_bits, row_bsize; | ||
351 | u32 val; | ||
352 | |||
353 | b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip; | ||
354 | b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; | ||
355 | b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; | ||
356 | b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; | ||
357 | b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf; | ||
358 | b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH; | ||
359 | b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */ | ||
360 | |||
361 | /* Enable NAND flash access */ | ||
362 | bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG, | ||
363 | BCMA_CC_4706_FLASHSCFG_NF1); | ||
364 | |||
365 | /* Configure wait counters */ | ||
366 | if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) { | ||
367 | freq = 100000000; | ||
368 | } else { | ||
369 | freq = bcma_chipco_pll_read(b47n->cc, 4); | ||
370 | freq = (freq * 0xFFF) >> 3; | ||
371 | freq = (freq * 25000000) >> 3; | ||
372 | } | ||
373 | clock = freq / 1000000; | ||
374 | w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock); | ||
375 | w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock); | ||
376 | w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock); | ||
377 | w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock); | ||
378 | w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock); | ||
379 | bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0, | ||
380 | (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0)); | ||
381 | |||
382 | /* Scan NAND */ | ||
383 | err = nand_scan(&b47n->mtd, 1); | ||
384 | if (err) { | ||
385 | pr_err("Could not scan NAND flash: %d\n", err); | ||
386 | goto exit; | ||
387 | } | ||
388 | |||
389 | /* Configure FLASH */ | ||
390 | chipsize = b47n->nand_chip.chipsize >> 20; | ||
391 | tbits = ffs(chipsize); /* find first bit set */ | ||
392 | if (!tbits || tbits != fls(chipsize)) { | ||
393 | pr_err("Invalid flash size: 0x%lX\n", chipsize); | ||
394 | err = -ENOTSUPP; | ||
395 | goto exit; | ||
396 | } | ||
397 | tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */ | ||
398 | |||
399 | col_bits = b47n->nand_chip.page_shift + 1; | ||
400 | col_size = (col_bits + 7) / 8; | ||
401 | |||
402 | row_bits = tbits - col_bits + 1; | ||
403 | row_bsize = (row_bits + 7) / 8; | ||
404 | |||
405 | val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2; | ||
406 | bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val); | ||
407 | |||
408 | exit: | ||
409 | if (err) | ||
410 | bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG, | ||
411 | ~BCMA_CC_4706_FLASHSCFG_NF1); | ||
412 | return err; | ||
413 | } | ||
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index ab0caa74eb43..4271e948d1e2 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -658,7 +658,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) | |||
658 | /* | 658 | /* |
659 | * Device management interface | 659 | * Device management interface |
660 | */ | 660 | */ |
661 | static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) | 661 | static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info) |
662 | { | 662 | { |
663 | struct mtd_info *mtd = &info->mtd; | 663 | struct mtd_info *mtd = &info->mtd; |
664 | struct mtd_partition *parts = info->platform->partitions; | 664 | struct mtd_partition *parts = info->platform->partitions; |
@@ -667,7 +667,7 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) | |||
667 | return mtd_device_register(mtd, parts, nr); | 667 | return mtd_device_register(mtd, parts, nr); |
668 | } | 668 | } |
669 | 669 | ||
670 | static int __devexit bf5xx_nand_remove(struct platform_device *pdev) | 670 | static int bf5xx_nand_remove(struct platform_device *pdev) |
671 | { | 671 | { |
672 | struct bf5xx_nand_info *info = to_nand_info(pdev); | 672 | struct bf5xx_nand_info *info = to_nand_info(pdev); |
673 | 673 | ||
@@ -725,7 +725,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd) | |||
725 | * it can allocate all necessary resources then calls the | 725 | * it can allocate all necessary resources then calls the |
726 | * nand layer to look for devices | 726 | * nand layer to look for devices |
727 | */ | 727 | */ |
728 | static int __devinit bf5xx_nand_probe(struct platform_device *pdev) | 728 | static int bf5xx_nand_probe(struct platform_device *pdev) |
729 | { | 729 | { |
730 | struct bf5xx_nand_platform *plat = to_nand_plat(pdev); | 730 | struct bf5xx_nand_platform *plat = to_nand_plat(pdev); |
731 | struct bf5xx_nand_info *info = NULL; | 731 | struct bf5xx_nand_info *info = NULL; |
@@ -865,7 +865,7 @@ static int bf5xx_nand_resume(struct platform_device *dev) | |||
865 | /* driver device registration */ | 865 | /* driver device registration */ |
866 | static struct platform_driver bf5xx_nand_driver = { | 866 | static struct platform_driver bf5xx_nand_driver = { |
867 | .probe = bf5xx_nand_probe, | 867 | .probe = bf5xx_nand_probe, |
868 | .remove = __devexit_p(bf5xx_nand_remove), | 868 | .remove = bf5xx_nand_remove, |
869 | .suspend = bf5xx_nand_suspend, | 869 | .suspend = bf5xx_nand_suspend, |
870 | .resume = bf5xx_nand_resume, | 870 | .resume = bf5xx_nand_resume, |
871 | .driver = { | 871 | .driver = { |
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 2bb7170502c2..010d61266536 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -585,7 +585,7 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
585 | } | 585 | } |
586 | 586 | ||
587 | /* F_2[X]/(X**6+X+1) */ | 587 | /* F_2[X]/(X**6+X+1) */ |
588 | static unsigned short __devinit gf64_mul(u8 a, u8 b) | 588 | static unsigned short gf64_mul(u8 a, u8 b) |
589 | { | 589 | { |
590 | u8 c; | 590 | u8 c; |
591 | unsigned int i; | 591 | unsigned int i; |
@@ -604,7 +604,7 @@ static unsigned short __devinit gf64_mul(u8 a, u8 b) | |||
604 | } | 604 | } |
605 | 605 | ||
606 | /* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X] */ | 606 | /* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X] */ |
607 | static u16 __devinit gf4096_mul(u16 a, u16 b) | 607 | static u16 gf4096_mul(u16 a, u16 b) |
608 | { | 608 | { |
609 | u8 ah, al, bh, bl, ch, cl; | 609 | u8 ah, al, bh, bl, ch, cl; |
610 | 610 | ||
@@ -619,14 +619,14 @@ static u16 __devinit gf4096_mul(u16 a, u16 b) | |||
619 | return (ch << 6) ^ cl; | 619 | return (ch << 6) ^ cl; |
620 | } | 620 | } |
621 | 621 | ||
622 | static int __devinit cafe_mul(int x) | 622 | static int cafe_mul(int x) |
623 | { | 623 | { |
624 | if (x == 0) | 624 | if (x == 0) |
625 | return 1; | 625 | return 1; |
626 | return gf4096_mul(x, 0xe01); | 626 | return gf4096_mul(x, 0xe01); |
627 | } | 627 | } |
628 | 628 | ||
629 | static int __devinit cafe_nand_probe(struct pci_dev *pdev, | 629 | static int cafe_nand_probe(struct pci_dev *pdev, |
630 | const struct pci_device_id *ent) | 630 | const struct pci_device_id *ent) |
631 | { | 631 | { |
632 | struct mtd_info *mtd; | 632 | struct mtd_info *mtd; |
@@ -821,7 +821,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
821 | return err; | 821 | return err; |
822 | } | 822 | } |
823 | 823 | ||
824 | static void __devexit cafe_nand_remove(struct pci_dev *pdev) | 824 | static void cafe_nand_remove(struct pci_dev *pdev) |
825 | { | 825 | { |
826 | struct mtd_info *mtd = pci_get_drvdata(pdev); | 826 | struct mtd_info *mtd = pci_get_drvdata(pdev); |
827 | struct cafe_priv *cafe = mtd->priv; | 827 | struct cafe_priv *cafe = mtd->priv; |
@@ -887,7 +887,7 @@ static struct pci_driver cafe_nand_pci_driver = { | |||
887 | .name = "CAFÉ NAND", | 887 | .name = "CAFÉ NAND", |
888 | .id_table = cafe_nand_tbl, | 888 | .id_table = cafe_nand_tbl, |
889 | .probe = cafe_nand_probe, | 889 | .probe = cafe_nand_probe, |
890 | .remove = __devexit_p(cafe_nand_remove), | 890 | .remove = cafe_nand_remove, |
891 | .resume = cafe_nand_resume, | 891 | .resume = cafe_nand_resume, |
892 | }; | 892 | }; |
893 | 893 | ||
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index adb6c3ef37fb..2cdeab8bebc4 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
237 | this->ecc.hwctl = cs_enable_hwecc; | 237 | this->ecc.hwctl = cs_enable_hwecc; |
238 | this->ecc.calculate = cs_calculate_ecc; | 238 | this->ecc.calculate = cs_calculate_ecc; |
239 | this->ecc.correct = nand_correct_data; | 239 | this->ecc.correct = nand_correct_data; |
240 | this->ecc.strength = 1; | ||
240 | 241 | ||
241 | /* Enable the following for a flash based bad block table */ | 242 | /* Enable the following for a flash based bad block table */ |
242 | this->bbt_options = NAND_BBT_USE_FLASH; | 243 | this->bbt_options = NAND_BBT_USE_FLASH; |
@@ -247,8 +248,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
247 | goto out_ior; | 248 | goto out_ior; |
248 | } | 249 | } |
249 | 250 | ||
250 | this->ecc.strength = 1; | ||
251 | |||
252 | new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); | 251 | new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); |
253 | 252 | ||
254 | cs553x_mtd[cs] = new_mtd; | 253 | cs553x_mtd[cs] = new_mtd; |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 945047ad0952..3502606f6480 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -821,9 +821,16 @@ syndrome_done: | |||
821 | if (ret < 0) | 821 | if (ret < 0) |
822 | goto err_scan; | 822 | goto err_scan; |
823 | 823 | ||
824 | ret = mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts, | 824 | if (pdata->parts) |
825 | pdata->nr_parts); | 825 | ret = mtd_device_parse_register(&info->mtd, NULL, NULL, |
826 | 826 | pdata->parts, pdata->nr_parts); | |
827 | else { | ||
828 | struct mtd_part_parser_data ppdata; | ||
829 | |||
830 | ppdata.of_node = pdev->dev.of_node; | ||
831 | ret = mtd_device_parse_register(&info->mtd, NULL, &ppdata, | ||
832 | NULL, 0); | ||
833 | } | ||
827 | if (ret < 0) | 834 | if (ret < 0) |
828 | goto err_scan; | 835 | goto err_scan; |
829 | 836 | ||
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index e706a237170f..0c8bb6bf8424 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -16,14 +16,12 @@ | |||
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | 16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | |||
20 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
22 | #include <linux/dma-mapping.h> | 21 | #include <linux/dma-mapping.h> |
23 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
24 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/pci.h> | ||
27 | #include <linux/mtd/mtd.h> | 25 | #include <linux/mtd/mtd.h> |
28 | #include <linux/module.h> | 26 | #include <linux/module.h> |
29 | 27 | ||
@@ -89,13 +87,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." | |||
89 | * format the bank into the proper bits for the controller */ | 87 | * format the bank into the proper bits for the controller */ |
90 | #define BANK(x) ((x) << 24) | 88 | #define BANK(x) ((x) << 24) |
91 | 89 | ||
92 | /* List of platforms this NAND controller has be integrated into */ | ||
93 | static const struct pci_device_id denali_pci_ids[] = { | ||
94 | { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, | ||
95 | { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, | ||
96 | { /* end: all zeroes */ } | ||
97 | }; | ||
98 | |||
99 | /* forward declarations */ | 90 | /* forward declarations */ |
100 | static void clear_interrupts(struct denali_nand_info *denali); | 91 | static void clear_interrupts(struct denali_nand_info *denali); |
101 | static uint32_t wait_for_irq(struct denali_nand_info *denali, | 92 | static uint32_t wait_for_irq(struct denali_nand_info *denali, |
@@ -699,7 +690,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) | |||
699 | 690 | ||
700 | if (comp_res == 0) { | 691 | if (comp_res == 0) { |
701 | /* timeout */ | 692 | /* timeout */ |
702 | printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", | 693 | pr_err("timeout occurred, status = 0x%x, mask = 0x%x\n", |
703 | intr_status, irq_mask); | 694 | intr_status, irq_mask); |
704 | 695 | ||
705 | intr_status = 0; | 696 | intr_status = 0; |
@@ -1305,8 +1296,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1305 | /* TODO: Read OOB data */ | 1296 | /* TODO: Read OOB data */ |
1306 | break; | 1297 | break; |
1307 | default: | 1298 | default: |
1308 | printk(KERN_ERR ": unsupported command" | 1299 | pr_err(": unsupported command received 0x%x\n", cmd); |
1309 | " received 0x%x\n", cmd); | ||
1310 | break; | 1300 | break; |
1311 | } | 1301 | } |
1312 | } | 1302 | } |
@@ -1425,107 +1415,48 @@ void denali_drv_init(struct denali_nand_info *denali) | |||
1425 | denali->irq_status = 0; | 1415 | denali->irq_status = 0; |
1426 | } | 1416 | } |
1427 | 1417 | ||
1428 | /* driver entry point */ | 1418 | int denali_init(struct denali_nand_info *denali) |
1429 | static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
1430 | { | 1419 | { |
1431 | int ret = -ENODEV; | 1420 | int ret; |
1432 | resource_size_t csr_base, mem_base; | ||
1433 | unsigned long csr_len, mem_len; | ||
1434 | struct denali_nand_info *denali; | ||
1435 | |||
1436 | denali = kzalloc(sizeof(*denali), GFP_KERNEL); | ||
1437 | if (!denali) | ||
1438 | return -ENOMEM; | ||
1439 | 1421 | ||
1440 | ret = pci_enable_device(dev); | 1422 | if (denali->platform == INTEL_CE4100) { |
1441 | if (ret) { | ||
1442 | printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); | ||
1443 | goto failed_alloc_memery; | ||
1444 | } | ||
1445 | |||
1446 | if (id->driver_data == INTEL_CE4100) { | ||
1447 | /* Due to a silicon limitation, we can only support | 1423 | /* Due to a silicon limitation, we can only support |
1448 | * ONFI timing mode 1 and below. | 1424 | * ONFI timing mode 1 and below. |
1449 | */ | 1425 | */ |
1450 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) { | 1426 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) { |
1451 | printk(KERN_ERR "Intel CE4100 only supports" | 1427 | pr_err("Intel CE4100 only supports ONFI timing mode 1 or below\n"); |
1452 | " ONFI timing mode 1 or below\n"); | 1428 | return -EINVAL; |
1453 | ret = -EINVAL; | ||
1454 | goto failed_enable_dev; | ||
1455 | } | ||
1456 | denali->platform = INTEL_CE4100; | ||
1457 | mem_base = pci_resource_start(dev, 0); | ||
1458 | mem_len = pci_resource_len(dev, 1); | ||
1459 | csr_base = pci_resource_start(dev, 1); | ||
1460 | csr_len = pci_resource_len(dev, 1); | ||
1461 | } else { | ||
1462 | denali->platform = INTEL_MRST; | ||
1463 | csr_base = pci_resource_start(dev, 0); | ||
1464 | csr_len = pci_resource_len(dev, 0); | ||
1465 | mem_base = pci_resource_start(dev, 1); | ||
1466 | mem_len = pci_resource_len(dev, 1); | ||
1467 | if (!mem_len) { | ||
1468 | mem_base = csr_base + csr_len; | ||
1469 | mem_len = csr_len; | ||
1470 | } | 1429 | } |
1471 | } | 1430 | } |
1472 | 1431 | ||
1473 | /* Is 32-bit DMA supported? */ | 1432 | /* Is 32-bit DMA supported? */ |
1474 | ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); | 1433 | ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32)); |
1475 | if (ret) { | 1434 | if (ret) { |
1476 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); | 1435 | pr_err("Spectra: no usable DMA configuration\n"); |
1477 | goto failed_enable_dev; | 1436 | return ret; |
1478 | } | 1437 | } |
1479 | denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf, | 1438 | denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf, |
1480 | DENALI_BUF_SIZE, | 1439 | DENALI_BUF_SIZE, |
1481 | DMA_BIDIRECTIONAL); | 1440 | DMA_BIDIRECTIONAL); |
1482 | 1441 | ||
1483 | if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) { | 1442 | if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) { |
1484 | dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n"); | 1443 | dev_err(denali->dev, "Spectra: failed to map DMA buffer\n"); |
1485 | goto failed_enable_dev; | 1444 | return -EIO; |
1486 | } | ||
1487 | |||
1488 | pci_set_master(dev); | ||
1489 | denali->dev = &dev->dev; | ||
1490 | denali->mtd.dev.parent = &dev->dev; | ||
1491 | |||
1492 | ret = pci_request_regions(dev, DENALI_NAND_NAME); | ||
1493 | if (ret) { | ||
1494 | printk(KERN_ERR "Spectra: Unable to request memory regions\n"); | ||
1495 | goto failed_dma_map; | ||
1496 | } | ||
1497 | |||
1498 | denali->flash_reg = ioremap_nocache(csr_base, csr_len); | ||
1499 | if (!denali->flash_reg) { | ||
1500 | printk(KERN_ERR "Spectra: Unable to remap memory region\n"); | ||
1501 | ret = -ENOMEM; | ||
1502 | goto failed_req_regions; | ||
1503 | } | ||
1504 | |||
1505 | denali->flash_mem = ioremap_nocache(mem_base, mem_len); | ||
1506 | if (!denali->flash_mem) { | ||
1507 | printk(KERN_ERR "Spectra: ioremap_nocache failed!"); | ||
1508 | ret = -ENOMEM; | ||
1509 | goto failed_remap_reg; | ||
1510 | } | 1445 | } |
1511 | 1446 | denali->mtd.dev.parent = denali->dev; | |
1512 | denali_hw_init(denali); | 1447 | denali_hw_init(denali); |
1513 | denali_drv_init(denali); | 1448 | denali_drv_init(denali); |
1514 | 1449 | ||
1515 | /* denali_isr register is done after all the hardware | 1450 | /* denali_isr register is done after all the hardware |
1516 | * initilization is finished*/ | 1451 | * initilization is finished*/ |
1517 | if (request_irq(dev->irq, denali_isr, IRQF_SHARED, | 1452 | if (request_irq(denali->irq, denali_isr, IRQF_SHARED, |
1518 | DENALI_NAND_NAME, denali)) { | 1453 | DENALI_NAND_NAME, denali)) { |
1519 | printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); | 1454 | pr_err("Spectra: Unable to allocate IRQ\n"); |
1520 | ret = -ENODEV; | 1455 | return -ENODEV; |
1521 | goto failed_remap_mem; | ||
1522 | } | 1456 | } |
1523 | 1457 | ||
1524 | /* now that our ISR is registered, we can enable interrupts */ | 1458 | /* now that our ISR is registered, we can enable interrupts */ |
1525 | denali_set_intr_modes(denali, true); | 1459 | denali_set_intr_modes(denali, true); |
1526 | |||
1527 | pci_set_drvdata(dev, denali); | ||
1528 | |||
1529 | denali->mtd.name = "denali-nand"; | 1460 | denali->mtd.name = "denali-nand"; |
1530 | denali->mtd.owner = THIS_MODULE; | 1461 | denali->mtd.owner = THIS_MODULE; |
1531 | denali->mtd.priv = &denali->nand; | 1462 | denali->mtd.priv = &denali->nand; |
@@ -1549,8 +1480,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1549 | */ | 1480 | */ |
1550 | if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { | 1481 | if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { |
1551 | ret = -ENODEV; | 1482 | ret = -ENODEV; |
1552 | printk(KERN_ERR "Spectra: device size not supported by this " | 1483 | pr_err("Spectra: device size not supported by this version of MTD."); |
1553 | "version of MTD."); | ||
1554 | goto failed_req_irq; | 1484 | goto failed_req_irq; |
1555 | } | 1485 | } |
1556 | 1486 | ||
@@ -1602,8 +1532,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1602 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + | 1532 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + |
1603 | ECC_8BITS * (denali->mtd.writesize / | 1533 | ECC_8BITS * (denali->mtd.writesize / |
1604 | ECC_SECTOR_SIZE))) { | 1534 | ECC_SECTOR_SIZE))) { |
1605 | printk(KERN_ERR "Your NAND chip OOB is not large enough to" | 1535 | pr_err("Your NAND chip OOB is not large enough to \ |
1606 | " contain 8bit ECC correction codes"); | 1536 | contain 8bit ECC correction codes"); |
1607 | goto failed_req_irq; | 1537 | goto failed_req_irq; |
1608 | } else { | 1538 | } else { |
1609 | denali->nand.ecc.strength = 8; | 1539 | denali->nand.ecc.strength = 8; |
@@ -1655,56 +1585,24 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1655 | 1585 | ||
1656 | ret = mtd_device_register(&denali->mtd, NULL, 0); | 1586 | ret = mtd_device_register(&denali->mtd, NULL, 0); |
1657 | if (ret) { | 1587 | if (ret) { |
1658 | dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n", | 1588 | dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n", |
1659 | ret); | 1589 | ret); |
1660 | goto failed_req_irq; | 1590 | goto failed_req_irq; |
1661 | } | 1591 | } |
1662 | return 0; | 1592 | return 0; |
1663 | 1593 | ||
1664 | failed_req_irq: | 1594 | failed_req_irq: |
1665 | denali_irq_cleanup(dev->irq, denali); | 1595 | denali_irq_cleanup(denali->irq, denali); |
1666 | failed_remap_mem: | 1596 | |
1667 | iounmap(denali->flash_mem); | ||
1668 | failed_remap_reg: | ||
1669 | iounmap(denali->flash_reg); | ||
1670 | failed_req_regions: | ||
1671 | pci_release_regions(dev); | ||
1672 | failed_dma_map: | ||
1673 | dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | ||
1674 | DMA_BIDIRECTIONAL); | ||
1675 | failed_enable_dev: | ||
1676 | pci_disable_device(dev); | ||
1677 | failed_alloc_memery: | ||
1678 | kfree(denali); | ||
1679 | return ret; | 1597 | return ret; |
1680 | } | 1598 | } |
1599 | EXPORT_SYMBOL(denali_init); | ||
1681 | 1600 | ||
1682 | /* driver exit point */ | 1601 | /* driver exit point */ |
1683 | static void denali_pci_remove(struct pci_dev *dev) | 1602 | void denali_remove(struct denali_nand_info *denali) |
1684 | { | 1603 | { |
1685 | struct denali_nand_info *denali = pci_get_drvdata(dev); | 1604 | denali_irq_cleanup(denali->irq, denali); |
1686 | 1605 | dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | |
1687 | nand_release(&denali->mtd); | 1606 | DMA_BIDIRECTIONAL); |
1688 | |||
1689 | denali_irq_cleanup(dev->irq, denali); | ||
1690 | |||
1691 | iounmap(denali->flash_reg); | ||
1692 | iounmap(denali->flash_mem); | ||
1693 | pci_release_regions(dev); | ||
1694 | pci_disable_device(dev); | ||
1695 | dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | ||
1696 | DMA_BIDIRECTIONAL); | ||
1697 | pci_set_drvdata(dev, NULL); | ||
1698 | kfree(denali); | ||
1699 | } | 1607 | } |
1700 | 1608 | EXPORT_SYMBOL(denali_remove); | |
1701 | MODULE_DEVICE_TABLE(pci, denali_pci_ids); | ||
1702 | |||
1703 | static struct pci_driver denali_pci_driver = { | ||
1704 | .name = DENALI_NAND_NAME, | ||
1705 | .id_table = denali_pci_ids, | ||
1706 | .probe = denali_pci_probe, | ||
1707 | .remove = denali_pci_remove, | ||
1708 | }; | ||
1709 | |||
1710 | module_pci_driver(denali_pci_driver); | ||
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index fabb9d56b39e..cec5712862c9 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h | |||
@@ -466,6 +466,7 @@ struct nand_buf { | |||
466 | 466 | ||
467 | #define INTEL_CE4100 1 | 467 | #define INTEL_CE4100 1 |
468 | #define INTEL_MRST 2 | 468 | #define INTEL_MRST 2 |
469 | #define DT 3 | ||
469 | 470 | ||
470 | struct denali_nand_info { | 471 | struct denali_nand_info { |
471 | struct mtd_info mtd; | 472 | struct mtd_info mtd; |
@@ -487,6 +488,7 @@ struct denali_nand_info { | |||
487 | uint32_t irq_status; | 488 | uint32_t irq_status; |
488 | int irq_debug_array[32]; | 489 | int irq_debug_array[32]; |
489 | int idx; | 490 | int idx; |
491 | int irq; | ||
490 | 492 | ||
491 | uint32_t devnum; /* represent how many nands connected */ | 493 | uint32_t devnum; /* represent how many nands connected */ |
492 | uint32_t fwblks; /* represent how many blocks FW used */ | 494 | uint32_t fwblks; /* represent how many blocks FW used */ |
@@ -496,4 +498,7 @@ struct denali_nand_info { | |||
496 | uint32_t max_banks; | 498 | uint32_t max_banks; |
497 | }; | 499 | }; |
498 | 500 | ||
501 | extern int denali_init(struct denali_nand_info *denali); | ||
502 | extern void denali_remove(struct denali_nand_info *denali); | ||
503 | |||
499 | #endif /*_LLD_NAND_*/ | 504 | #endif /*_LLD_NAND_*/ |
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c new file mode 100644 index 000000000000..546f8cb5688d --- /dev/null +++ b/drivers/mtd/nand/denali_dt.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * NAND Flash Controller Device Driver for DT | ||
3 | * | ||
4 | * Copyright © 2011, Picochip. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #include "denali.h" | ||
27 | |||
28 | struct denali_dt { | ||
29 | struct denali_nand_info denali; | ||
30 | struct clk *clk; | ||
31 | }; | ||
32 | |||
33 | static void __iomem *request_and_map(struct device *dev, | ||
34 | const struct resource *res) | ||
35 | { | ||
36 | void __iomem *ptr; | ||
37 | |||
38 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | ||
39 | "denali-dt")) { | ||
40 | dev_err(dev, "unable to request %s\n", res->name); | ||
41 | return NULL; | ||
42 | } | ||
43 | |||
44 | ptr = devm_ioremap_nocache(dev, res->start, resource_size(res)); | ||
45 | if (!res) | ||
46 | dev_err(dev, "ioremap_nocache of %s failed!", res->name); | ||
47 | |||
48 | return ptr; | ||
49 | } | ||
50 | |||
51 | static const struct of_device_id denali_nand_dt_ids[] = { | ||
52 | { .compatible = "denali,denali-nand-dt" }, | ||
53 | { /* sentinel */ } | ||
54 | }; | ||
55 | |||
56 | MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); | ||
57 | |||
58 | static u64 denali_dma_mask; | ||
59 | |||
60 | static int denali_dt_probe(struct platform_device *ofdev) | ||
61 | { | ||
62 | struct resource *denali_reg, *nand_data; | ||
63 | struct denali_dt *dt; | ||
64 | struct denali_nand_info *denali; | ||
65 | int ret; | ||
66 | const struct of_device_id *of_id; | ||
67 | |||
68 | of_id = of_match_device(denali_nand_dt_ids, &ofdev->dev); | ||
69 | if (of_id) { | ||
70 | ofdev->id_entry = of_id->data; | ||
71 | } else { | ||
72 | pr_err("Failed to find the right device id.\n"); | ||
73 | return -ENOMEM; | ||
74 | } | ||
75 | |||
76 | dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL); | ||
77 | if (!dt) | ||
78 | return -ENOMEM; | ||
79 | denali = &dt->denali; | ||
80 | |||
81 | denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg"); | ||
82 | nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data"); | ||
83 | if (!denali_reg || !nand_data) { | ||
84 | dev_err(&ofdev->dev, "resources not completely defined\n"); | ||
85 | return -EINVAL; | ||
86 | } | ||
87 | |||
88 | denali->platform = DT; | ||
89 | denali->dev = &ofdev->dev; | ||
90 | denali->irq = platform_get_irq(ofdev, 0); | ||
91 | if (denali->irq < 0) { | ||
92 | dev_err(&ofdev->dev, "no irq defined\n"); | ||
93 | return -ENXIO; | ||
94 | } | ||
95 | |||
96 | denali->flash_reg = request_and_map(&ofdev->dev, denali_reg); | ||
97 | if (!denali->flash_reg) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | denali->flash_mem = request_and_map(&ofdev->dev, nand_data); | ||
101 | if (!denali->flash_mem) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | if (!of_property_read_u32(ofdev->dev.of_node, | ||
105 | "dma-mask", (u32 *)&denali_dma_mask)) { | ||
106 | denali->dev->dma_mask = &denali_dma_mask; | ||
107 | } else { | ||
108 | denali->dev->dma_mask = NULL; | ||
109 | } | ||
110 | |||
111 | dt->clk = clk_get(&ofdev->dev, NULL); | ||
112 | if (IS_ERR(dt->clk)) { | ||
113 | dev_err(&ofdev->dev, "no clk available\n"); | ||
114 | return PTR_ERR(dt->clk); | ||
115 | } | ||
116 | clk_prepare_enable(dt->clk); | ||
117 | |||
118 | ret = denali_init(denali); | ||
119 | if (ret) | ||
120 | goto out_disable_clk; | ||
121 | |||
122 | platform_set_drvdata(ofdev, dt); | ||
123 | return 0; | ||
124 | |||
125 | out_disable_clk: | ||
126 | clk_disable_unprepare(dt->clk); | ||
127 | clk_put(dt->clk); | ||
128 | |||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | static int denali_dt_remove(struct platform_device *ofdev) | ||
133 | { | ||
134 | struct denali_dt *dt = platform_get_drvdata(ofdev); | ||
135 | |||
136 | denali_remove(&dt->denali); | ||
137 | clk_disable(dt->clk); | ||
138 | clk_put(dt->clk); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static struct platform_driver denali_dt_driver = { | ||
144 | .probe = denali_dt_probe, | ||
145 | .remove = denali_dt_remove, | ||
146 | .driver = { | ||
147 | .name = "denali-nand-dt", | ||
148 | .owner = THIS_MODULE, | ||
149 | .of_match_table = of_match_ptr(denali_nand_dt_ids), | ||
150 | }, | ||
151 | }; | ||
152 | |||
153 | static int __init denali_init_dt(void) | ||
154 | { | ||
155 | return platform_driver_register(&denali_dt_driver); | ||
156 | } | ||
157 | module_init(denali_init_dt); | ||
158 | |||
159 | static void __exit denali_exit_dt(void) | ||
160 | { | ||
161 | platform_driver_unregister(&denali_dt_driver); | ||
162 | } | ||
163 | module_exit(denali_exit_dt); | ||
164 | |||
165 | MODULE_LICENSE("GPL"); | ||
166 | MODULE_AUTHOR("Jamie Iles"); | ||
167 | MODULE_DESCRIPTION("DT driver for Denali NAND controller"); | ||
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c new file mode 100644 index 000000000000..e3e46623b2b4 --- /dev/null +++ b/drivers/mtd/nand/denali_pci.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * NAND Flash Controller Device Driver | ||
3 | * Copyright © 2009-2010, Intel Corporation and its suppliers. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/slab.h> | ||
18 | |||
19 | #include "denali.h" | ||
20 | |||
21 | #define DENALI_NAND_NAME "denali-nand-pci" | ||
22 | |||
23 | /* List of platforms this NAND controller has be integrated into */ | ||
24 | static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = { | ||
25 | { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, | ||
26 | { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, | ||
27 | { /* end: all zeroes */ } | ||
28 | }; | ||
29 | MODULE_DEVICE_TABLE(pci, denali_pci_ids); | ||
30 | |||
31 | static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
32 | { | ||
33 | int ret = -ENODEV; | ||
34 | resource_size_t csr_base, mem_base; | ||
35 | unsigned long csr_len, mem_len; | ||
36 | struct denali_nand_info *denali; | ||
37 | |||
38 | denali = kzalloc(sizeof(*denali), GFP_KERNEL); | ||
39 | if (!denali) | ||
40 | return -ENOMEM; | ||
41 | |||
42 | ret = pci_enable_device(dev); | ||
43 | if (ret) { | ||
44 | pr_err("Spectra: pci_enable_device failed.\n"); | ||
45 | goto failed_alloc_memery; | ||
46 | } | ||
47 | |||
48 | if (id->driver_data == INTEL_CE4100) { | ||
49 | denali->platform = INTEL_CE4100; | ||
50 | mem_base = pci_resource_start(dev, 0); | ||
51 | mem_len = pci_resource_len(dev, 1); | ||
52 | csr_base = pci_resource_start(dev, 1); | ||
53 | csr_len = pci_resource_len(dev, 1); | ||
54 | } else { | ||
55 | denali->platform = INTEL_MRST; | ||
56 | csr_base = pci_resource_start(dev, 0); | ||
57 | csr_len = pci_resource_len(dev, 0); | ||
58 | mem_base = pci_resource_start(dev, 1); | ||
59 | mem_len = pci_resource_len(dev, 1); | ||
60 | if (!mem_len) { | ||
61 | mem_base = csr_base + csr_len; | ||
62 | mem_len = csr_len; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | pci_set_master(dev); | ||
67 | denali->dev = &dev->dev; | ||
68 | denali->irq = dev->irq; | ||
69 | |||
70 | ret = pci_request_regions(dev, DENALI_NAND_NAME); | ||
71 | if (ret) { | ||
72 | pr_err("Spectra: Unable to request memory regions\n"); | ||
73 | goto failed_enable_dev; | ||
74 | } | ||
75 | |||
76 | denali->flash_reg = ioremap_nocache(csr_base, csr_len); | ||
77 | if (!denali->flash_reg) { | ||
78 | pr_err("Spectra: Unable to remap memory region\n"); | ||
79 | ret = -ENOMEM; | ||
80 | goto failed_req_regions; | ||
81 | } | ||
82 | |||
83 | denali->flash_mem = ioremap_nocache(mem_base, mem_len); | ||
84 | if (!denali->flash_mem) { | ||
85 | pr_err("Spectra: ioremap_nocache failed!"); | ||
86 | ret = -ENOMEM; | ||
87 | goto failed_remap_reg; | ||
88 | } | ||
89 | |||
90 | ret = denali_init(denali); | ||
91 | if (ret) | ||
92 | goto failed_remap_mem; | ||
93 | |||
94 | pci_set_drvdata(dev, denali); | ||
95 | |||
96 | return 0; | ||
97 | |||
98 | failed_remap_mem: | ||
99 | iounmap(denali->flash_mem); | ||
100 | failed_remap_reg: | ||
101 | iounmap(denali->flash_reg); | ||
102 | failed_req_regions: | ||
103 | pci_release_regions(dev); | ||
104 | failed_enable_dev: | ||
105 | pci_disable_device(dev); | ||
106 | failed_alloc_memery: | ||
107 | kfree(denali); | ||
108 | |||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | /* driver exit point */ | ||
113 | static void denali_pci_remove(struct pci_dev *dev) | ||
114 | { | ||
115 | struct denali_nand_info *denali = pci_get_drvdata(dev); | ||
116 | |||
117 | denali_remove(denali); | ||
118 | iounmap(denali->flash_reg); | ||
119 | iounmap(denali->flash_mem); | ||
120 | pci_release_regions(dev); | ||
121 | pci_disable_device(dev); | ||
122 | pci_set_drvdata(dev, NULL); | ||
123 | kfree(denali); | ||
124 | } | ||
125 | |||
126 | static struct pci_driver denali_pci_driver = { | ||
127 | .name = DENALI_NAND_NAME, | ||
128 | .id_table = denali_pci_ids, | ||
129 | .probe = denali_pci_probe, | ||
130 | .remove = denali_pci_remove, | ||
131 | }; | ||
132 | |||
133 | static int denali_init_pci(void) | ||
134 | { | ||
135 | pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__); | ||
136 | return pci_register_driver(&denali_pci_driver); | ||
137 | } | ||
138 | module_init(denali_init_pci); | ||
139 | |||
140 | static void denali_exit_pci(void) | ||
141 | { | ||
142 | pci_unregister_driver(&denali_pci_driver); | ||
143 | } | ||
144 | module_exit(denali_exit_pci); | ||
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 256eb30f6180..81fa5784f98b 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -53,8 +53,6 @@ static unsigned long __initdata doc_locations[] = { | |||
53 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, | 53 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, |
54 | 0xe8000, 0xea000, 0xec000, 0xee000, | 54 | 0xe8000, 0xea000, 0xec000, 0xee000, |
55 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ | 55 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ |
56 | #else | ||
57 | #warning Unknown architecture for DiskOnChip. No default probe locations defined | ||
58 | #endif | 56 | #endif |
59 | 0xffffffff }; | 57 | 0xffffffff }; |
60 | 58 | ||
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index 799da5d1c857..18fa4489e52e 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c | |||
@@ -46,6 +46,25 @@ | |||
46 | #include <linux/bitrev.h> | 46 | #include <linux/bitrev.h> |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * In "reliable mode" consecutive 2k pages are used in parallel (in some | ||
50 | * fashion) to store the same data. The data can be read back from the | ||
51 | * even-numbered pages in the normal manner; odd-numbered pages will appear to | ||
52 | * contain junk. Systems that boot from the docg4 typically write the secondary | ||
53 | * program loader (SPL) code in this mode. The SPL is loaded by the initial | ||
54 | * program loader (IPL, stored in the docg4's 2k NOR-like region that is mapped | ||
55 | * to the reset vector address). This module parameter enables you to use this | ||
56 | * driver to write the SPL. When in this mode, no more than 2k of data can be | ||
57 | * written at a time, because the addresses do not increment in the normal | ||
58 | * manner, and the starting offset must be within an even-numbered 2k region; | ||
59 | * i.e., invalid starting offsets are 0x800, 0xa00, 0xc00, 0xe00, 0x1800, | ||
60 | * 0x1a00, ... Reliable mode is a special case and should not be used unless | ||
61 | * you know what you're doing. | ||
62 | */ | ||
63 | static bool reliable_mode; | ||
64 | module_param(reliable_mode, bool, 0); | ||
65 | MODULE_PARM_DESC(reliable_mode, "pages are programmed in reliable mode"); | ||
66 | |||
67 | /* | ||
49 | * You'll want to ignore badblocks if you're reading a partition that contains | 68 | * You'll want to ignore badblocks if you're reading a partition that contains |
50 | * data written by the TrueFFS library (i.e., by PalmOS, Windows, etc), since | 69 | * data written by the TrueFFS library (i.e., by PalmOS, Windows, etc), since |
51 | * it does not use mtd nand's method for marking bad blocks (using oob area). | 70 | * it does not use mtd nand's method for marking bad blocks (using oob area). |
@@ -113,6 +132,7 @@ struct docg4_priv { | |||
113 | #define DOCG4_SEQ_PAGEWRITE 0x16 | 132 | #define DOCG4_SEQ_PAGEWRITE 0x16 |
114 | #define DOCG4_SEQ_PAGEPROG 0x1e | 133 | #define DOCG4_SEQ_PAGEPROG 0x1e |
115 | #define DOCG4_SEQ_BLOCKERASE 0x24 | 134 | #define DOCG4_SEQ_BLOCKERASE 0x24 |
135 | #define DOCG4_SEQ_SETMODE 0x45 | ||
116 | 136 | ||
117 | /* DOC_FLASHCOMMAND register commands */ | 137 | /* DOC_FLASHCOMMAND register commands */ |
118 | #define DOCG4_CMD_PAGE_READ 0x00 | 138 | #define DOCG4_CMD_PAGE_READ 0x00 |
@@ -122,6 +142,8 @@ struct docg4_priv { | |||
122 | #define DOC_CMD_PROG_BLOCK_ADDR 0x60 | 142 | #define DOC_CMD_PROG_BLOCK_ADDR 0x60 |
123 | #define DOCG4_CMD_PAGEWRITE 0x80 | 143 | #define DOCG4_CMD_PAGEWRITE 0x80 |
124 | #define DOC_CMD_PROG_CYCLE2 0x10 | 144 | #define DOC_CMD_PROG_CYCLE2 0x10 |
145 | #define DOCG4_CMD_FAST_MODE 0xa3 /* functionality guessed */ | ||
146 | #define DOC_CMD_RELIABLE_MODE 0x22 | ||
125 | #define DOC_CMD_RESET 0xff | 147 | #define DOC_CMD_RESET 0xff |
126 | 148 | ||
127 | /* DOC_POWERMODE register bits */ | 149 | /* DOC_POWERMODE register bits */ |
@@ -190,17 +212,20 @@ struct docg4_priv { | |||
190 | #define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */ | 212 | #define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */ |
191 | 213 | ||
192 | #define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */ | 214 | #define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */ |
215 | #define DOCG4_REDUNDANT_BBT_PAGE 24 /* page where redundant factory bbt lives */ | ||
193 | 216 | ||
194 | /* | 217 | /* |
195 | * Oob bytes 0 - 6 are available to the user. | 218 | * Bytes 0, 1 are used as badblock marker. |
196 | * Byte 7 is hamming ecc for first 7 bytes. Bytes 8 - 14 are hw-generated ecc. | 219 | * Bytes 2 - 6 are available to the user. |
220 | * Byte 7 is hamming ecc for first 7 oob bytes only. | ||
221 | * Bytes 8 - 14 are hw-generated ecc covering entire page + oob bytes 0 - 14. | ||
197 | * Byte 15 (the last) is used by the driver as a "page written" flag. | 222 | * Byte 15 (the last) is used by the driver as a "page written" flag. |
198 | */ | 223 | */ |
199 | static struct nand_ecclayout docg4_oobinfo = { | 224 | static struct nand_ecclayout docg4_oobinfo = { |
200 | .eccbytes = 9, | 225 | .eccbytes = 9, |
201 | .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, | 226 | .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, |
202 | .oobavail = 7, | 227 | .oobavail = 5, |
203 | .oobfree = { {0, 7} } | 228 | .oobfree = { {.offset = 2, .length = 5} } |
204 | }; | 229 | }; |
205 | 230 | ||
206 | /* | 231 | /* |
@@ -611,6 +636,14 @@ static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) | |||
611 | dev_dbg(doc->dev, | 636 | dev_dbg(doc->dev, |
612 | "docg4: %s: g4 addr: %x\n", __func__, docg4_addr); | 637 | "docg4: %s: g4 addr: %x\n", __func__, docg4_addr); |
613 | sequence_reset(mtd); | 638 | sequence_reset(mtd); |
639 | |||
640 | if (unlikely(reliable_mode)) { | ||
641 | writew(DOCG4_SEQ_SETMODE, docptr + DOC_FLASHSEQUENCE); | ||
642 | writew(DOCG4_CMD_FAST_MODE, docptr + DOC_FLASHCOMMAND); | ||
643 | writew(DOC_CMD_RELIABLE_MODE, docptr + DOC_FLASHCOMMAND); | ||
644 | write_nop(docptr); | ||
645 | } | ||
646 | |||
614 | writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE); | 647 | writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE); |
615 | writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND); | 648 | writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND); |
616 | write_nop(docptr); | 649 | write_nop(docptr); |
@@ -691,6 +724,15 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column, | |||
691 | break; | 724 | break; |
692 | 725 | ||
693 | case NAND_CMD_SEQIN: | 726 | case NAND_CMD_SEQIN: |
727 | if (unlikely(reliable_mode)) { | ||
728 | uint16_t g4_page = g4_addr >> 16; | ||
729 | |||
730 | /* writes to odd-numbered 2k pages are invalid */ | ||
731 | if (g4_page & 0x01) | ||
732 | dev_warn(doc->dev, | ||
733 | "invalid reliable mode address\n"); | ||
734 | } | ||
735 | |||
694 | write_page_prologue(mtd, g4_addr); | 736 | write_page_prologue(mtd, g4_addr); |
695 | 737 | ||
696 | /* hack for deferred write of oob bytes */ | 738 | /* hack for deferred write of oob bytes */ |
@@ -979,16 +1021,15 @@ static int __init read_factory_bbt(struct mtd_info *mtd) | |||
979 | struct docg4_priv *doc = nand->priv; | 1021 | struct docg4_priv *doc = nand->priv; |
980 | uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); | 1022 | uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); |
981 | uint8_t *buf; | 1023 | uint8_t *buf; |
982 | int i, block, status; | 1024 | int i, block; |
1025 | __u32 eccfailed_stats = mtd->ecc_stats.failed; | ||
983 | 1026 | ||
984 | buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL); | 1027 | buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL); |
985 | if (buf == NULL) | 1028 | if (buf == NULL) |
986 | return -ENOMEM; | 1029 | return -ENOMEM; |
987 | 1030 | ||
988 | read_page_prologue(mtd, g4_addr); | 1031 | read_page_prologue(mtd, g4_addr); |
989 | status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); | 1032 | docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); |
990 | if (status) | ||
991 | goto exit; | ||
992 | 1033 | ||
993 | /* | 1034 | /* |
994 | * If no memory-based bbt was created, exit. This will happen if module | 1035 | * If no memory-based bbt was created, exit. This will happen if module |
@@ -1000,6 +1041,20 @@ static int __init read_factory_bbt(struct mtd_info *mtd) | |||
1000 | if (nand->bbt == NULL) /* no memory-based bbt */ | 1041 | if (nand->bbt == NULL) /* no memory-based bbt */ |
1001 | goto exit; | 1042 | goto exit; |
1002 | 1043 | ||
1044 | if (mtd->ecc_stats.failed > eccfailed_stats) { | ||
1045 | /* | ||
1046 | * Whoops, an ecc failure ocurred reading the factory bbt. | ||
1047 | * It is stored redundantly, so we get another chance. | ||
1048 | */ | ||
1049 | eccfailed_stats = mtd->ecc_stats.failed; | ||
1050 | docg4_read_page(mtd, nand, buf, 0, DOCG4_REDUNDANT_BBT_PAGE); | ||
1051 | if (mtd->ecc_stats.failed > eccfailed_stats) { | ||
1052 | dev_warn(doc->dev, | ||
1053 | "The factory bbt could not be read!\n"); | ||
1054 | goto exit; | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1003 | /* | 1058 | /* |
1004 | * Parse factory bbt and update memory-based bbt. Factory bbt format is | 1059 | * Parse factory bbt and update memory-based bbt. Factory bbt format is |
1005 | * simple: one bit per block, block numbers increase left to right (msb | 1060 | * simple: one bit per block, block numbers increase left to right (msb |
@@ -1019,7 +1074,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) | |||
1019 | } | 1074 | } |
1020 | exit: | 1075 | exit: |
1021 | kfree(buf); | 1076 | kfree(buf); |
1022 | return status; | 1077 | return 0; |
1023 | } | 1078 | } |
1024 | 1079 | ||
1025 | static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) | 1080 | static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index cc1480a5e4c1..20657209a472 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -109,20 +109,6 @@ static struct nand_ecclayout fsl_elbc_oob_lp_eccm1 = { | |||
109 | }; | 109 | }; |
110 | 110 | ||
111 | /* | 111 | /* |
112 | * fsl_elbc_oob_lp_eccm* specify that LP NAND's OOB free area starts at offset | ||
113 | * 1, so we have to adjust bad block pattern. This pattern should be used for | ||
114 | * x8 chips only. So far hardware does not support x16 chips anyway. | ||
115 | */ | ||
116 | static u8 scan_ff_pattern[] = { 0xff, }; | ||
117 | |||
118 | static struct nand_bbt_descr largepage_memorybased = { | ||
119 | .options = 0, | ||
120 | .offs = 0, | ||
121 | .len = 1, | ||
122 | .pattern = scan_ff_pattern, | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt, | 112 | * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt, |
127 | * interfere with ECC positions, that's why we implement our own descriptors. | 113 | * interfere with ECC positions, that's why we implement our own descriptors. |
128 | * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0. | 114 | * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0. |
@@ -699,7 +685,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
699 | chip->ecc.layout = (priv->fmr & FMR_ECCM) ? | 685 | chip->ecc.layout = (priv->fmr & FMR_ECCM) ? |
700 | &fsl_elbc_oob_lp_eccm1 : | 686 | &fsl_elbc_oob_lp_eccm1 : |
701 | &fsl_elbc_oob_lp_eccm0; | 687 | &fsl_elbc_oob_lp_eccm0; |
702 | chip->badblock_pattern = &largepage_memorybased; | ||
703 | } | 688 | } |
704 | } else { | 689 | } else { |
705 | dev_err(priv->dev, | 690 | dev_err(priv->dev, |
@@ -814,7 +799,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |||
814 | 799 | ||
815 | static DEFINE_MUTEX(fsl_elbc_nand_mutex); | 800 | static DEFINE_MUTEX(fsl_elbc_nand_mutex); |
816 | 801 | ||
817 | static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | 802 | static int fsl_elbc_nand_probe(struct platform_device *pdev) |
818 | { | 803 | { |
819 | struct fsl_lbc_regs __iomem *lbc; | 804 | struct fsl_lbc_regs __iomem *lbc; |
820 | struct fsl_elbc_mtd *priv; | 805 | struct fsl_elbc_mtd *priv; |
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 3551a99076ba..ad6222627fed 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c | |||
@@ -389,7 +389,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
389 | timing = IFC_FIR_OP_RBCD; | 389 | timing = IFC_FIR_OP_RBCD; |
390 | 390 | ||
391 | out_be32(&ifc->ifc_nand.nand_fir0, | 391 | out_be32(&ifc->ifc_nand.nand_fir0, |
392 | (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | | 392 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | |
393 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | | 393 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | |
394 | (timing << IFC_NAND_FIR0_OP2_SHIFT)); | 394 | (timing << IFC_NAND_FIR0_OP2_SHIFT)); |
395 | out_be32(&ifc->ifc_nand.nand_fcr0, | 395 | out_be32(&ifc->ifc_nand.nand_fcr0, |
@@ -754,7 +754,7 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) | |||
754 | 754 | ||
755 | /* READID */ | 755 | /* READID */ |
756 | out_be32(&ifc->ifc_nand.nand_fir0, | 756 | out_be32(&ifc->ifc_nand.nand_fir0, |
757 | (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | | 757 | (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | |
758 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | | 758 | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | |
759 | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); | 759 | (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); |
760 | out_be32(&ifc->ifc_nand.nand_fcr0, | 760 | out_be32(&ifc->ifc_nand.nand_fcr0, |
@@ -922,7 +922,7 @@ static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank, | |||
922 | 922 | ||
923 | static DEFINE_MUTEX(fsl_ifc_nand_mutex); | 923 | static DEFINE_MUTEX(fsl_ifc_nand_mutex); |
924 | 924 | ||
925 | static int __devinit fsl_ifc_nand_probe(struct platform_device *dev) | 925 | static int fsl_ifc_nand_probe(struct platform_device *dev) |
926 | { | 926 | { |
927 | struct fsl_ifc_regs __iomem *ifc; | 927 | struct fsl_ifc_regs __iomem *ifc; |
928 | struct fsl_ifc_mtd *priv; | 928 | struct fsl_ifc_mtd *priv; |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 45df542b9c61..5a8f5c4ce512 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -152,7 +152,7 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
152 | fun_wait_rnb(fun); | 152 | fun_wait_rnb(fun); |
153 | } | 153 | } |
154 | 154 | ||
155 | static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | 155 | static int fun_chip_init(struct fsl_upm_nand *fun, |
156 | const struct device_node *upm_np, | 156 | const struct device_node *upm_np, |
157 | const struct resource *io_res) | 157 | const struct resource *io_res) |
158 | { | 158 | { |
@@ -201,7 +201,7 @@ err: | |||
201 | return ret; | 201 | return ret; |
202 | } | 202 | } |
203 | 203 | ||
204 | static int __devinit fun_probe(struct platform_device *ofdev) | 204 | static int fun_probe(struct platform_device *ofdev) |
205 | { | 205 | { |
206 | struct fsl_upm_nand *fun; | 206 | struct fsl_upm_nand *fun; |
207 | struct resource io_res; | 207 | struct resource io_res; |
@@ -318,7 +318,7 @@ err1: | |||
318 | return ret; | 318 | return ret; |
319 | } | 319 | } |
320 | 320 | ||
321 | static int __devexit fun_remove(struct platform_device *ofdev) | 321 | static int fun_remove(struct platform_device *ofdev) |
322 | { | 322 | { |
323 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); | 323 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); |
324 | int i; | 324 | int i; |
@@ -350,7 +350,7 @@ static struct platform_driver of_fun_driver = { | |||
350 | .of_match_table = of_fun_match, | 350 | .of_match_table = of_fun_match, |
351 | }, | 351 | }, |
352 | .probe = fun_probe, | 352 | .probe = fun_probe, |
353 | .remove = __devexit_p(fun_remove), | 353 | .remove = fun_remove, |
354 | }; | 354 | }; |
355 | 355 | ||
356 | module_platform_driver(of_fun_driver); | 356 | module_platform_driver(of_fun_driver); |
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 38d26240d8b1..1d7446434b0e 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -361,7 +361,7 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
361 | struct nand_chip *this = mtd->priv; | 361 | struct nand_chip *this = mtd->priv; |
362 | struct fsmc_nand_data *host = container_of(mtd, | 362 | struct fsmc_nand_data *host = container_of(mtd, |
363 | struct fsmc_nand_data, mtd); | 363 | struct fsmc_nand_data, mtd); |
364 | void *__iomem *regs = host->regs_va; | 364 | void __iomem *regs = host->regs_va; |
365 | unsigned int bank = host->bank; | 365 | unsigned int bank = host->bank; |
366 | 366 | ||
367 | if (ctrl & NAND_CTRL_CHANGE) { | 367 | if (ctrl & NAND_CTRL_CHANGE) { |
@@ -383,13 +383,13 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
383 | pc |= FSMC_ENABLE; | 383 | pc |= FSMC_ENABLE; |
384 | else | 384 | else |
385 | pc &= ~FSMC_ENABLE; | 385 | pc &= ~FSMC_ENABLE; |
386 | writel(pc, FSMC_NAND_REG(regs, bank, PC)); | 386 | writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC)); |
387 | } | 387 | } |
388 | 388 | ||
389 | mb(); | 389 | mb(); |
390 | 390 | ||
391 | if (cmd != NAND_CMD_NONE) | 391 | if (cmd != NAND_CMD_NONE) |
392 | writeb(cmd, this->IO_ADDR_W); | 392 | writeb_relaxed(cmd, this->IO_ADDR_W); |
393 | } | 393 | } |
394 | 394 | ||
395 | /* | 395 | /* |
@@ -426,14 +426,18 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank, | |||
426 | tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT; | 426 | tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT; |
427 | 427 | ||
428 | if (busw) | 428 | if (busw) |
429 | writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC)); | 429 | writel_relaxed(value | FSMC_DEVWID_16, |
430 | FSMC_NAND_REG(regs, bank, PC)); | ||
430 | else | 431 | else |
431 | writel(value | FSMC_DEVWID_8, FSMC_NAND_REG(regs, bank, PC)); | 432 | writel_relaxed(value | FSMC_DEVWID_8, |
433 | FSMC_NAND_REG(regs, bank, PC)); | ||
432 | 434 | ||
433 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar, | 435 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar, |
434 | FSMC_NAND_REG(regs, bank, PC)); | 436 | FSMC_NAND_REG(regs, bank, PC)); |
435 | writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, COMM)); | 437 | writel_relaxed(thiz | thold | twait | tset, |
436 | writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, ATTRIB)); | 438 | FSMC_NAND_REG(regs, bank, COMM)); |
439 | writel_relaxed(thiz | thold | twait | tset, | ||
440 | FSMC_NAND_REG(regs, bank, ATTRIB)); | ||
437 | } | 441 | } |
438 | 442 | ||
439 | /* | 443 | /* |
@@ -446,11 +450,11 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) | |||
446 | void __iomem *regs = host->regs_va; | 450 | void __iomem *regs = host->regs_va; |
447 | uint32_t bank = host->bank; | 451 | uint32_t bank = host->bank; |
448 | 452 | ||
449 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256, | 453 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256, |
450 | FSMC_NAND_REG(regs, bank, PC)); | 454 | FSMC_NAND_REG(regs, bank, PC)); |
451 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN, | 455 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN, |
452 | FSMC_NAND_REG(regs, bank, PC)); | 456 | FSMC_NAND_REG(regs, bank, PC)); |
453 | writel(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN, | 457 | writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN, |
454 | FSMC_NAND_REG(regs, bank, PC)); | 458 | FSMC_NAND_REG(regs, bank, PC)); |
455 | } | 459 | } |
456 | 460 | ||
@@ -470,7 +474,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, | |||
470 | unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; | 474 | unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; |
471 | 475 | ||
472 | do { | 476 | do { |
473 | if (readl(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY) | 477 | if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY) |
474 | break; | 478 | break; |
475 | else | 479 | else |
476 | cond_resched(); | 480 | cond_resched(); |
@@ -481,25 +485,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, | |||
481 | return -ETIMEDOUT; | 485 | return -ETIMEDOUT; |
482 | } | 486 | } |
483 | 487 | ||
484 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1)); | 488 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); |
485 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | 489 | ecc[0] = (uint8_t) (ecc_tmp >> 0); |
486 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | 490 | ecc[1] = (uint8_t) (ecc_tmp >> 8); |
487 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | 491 | ecc[2] = (uint8_t) (ecc_tmp >> 16); |
488 | ecc[3] = (uint8_t) (ecc_tmp >> 24); | 492 | ecc[3] = (uint8_t) (ecc_tmp >> 24); |
489 | 493 | ||
490 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC2)); | 494 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2)); |
491 | ecc[4] = (uint8_t) (ecc_tmp >> 0); | 495 | ecc[4] = (uint8_t) (ecc_tmp >> 0); |
492 | ecc[5] = (uint8_t) (ecc_tmp >> 8); | 496 | ecc[5] = (uint8_t) (ecc_tmp >> 8); |
493 | ecc[6] = (uint8_t) (ecc_tmp >> 16); | 497 | ecc[6] = (uint8_t) (ecc_tmp >> 16); |
494 | ecc[7] = (uint8_t) (ecc_tmp >> 24); | 498 | ecc[7] = (uint8_t) (ecc_tmp >> 24); |
495 | 499 | ||
496 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC3)); | 500 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3)); |
497 | ecc[8] = (uint8_t) (ecc_tmp >> 0); | 501 | ecc[8] = (uint8_t) (ecc_tmp >> 0); |
498 | ecc[9] = (uint8_t) (ecc_tmp >> 8); | 502 | ecc[9] = (uint8_t) (ecc_tmp >> 8); |
499 | ecc[10] = (uint8_t) (ecc_tmp >> 16); | 503 | ecc[10] = (uint8_t) (ecc_tmp >> 16); |
500 | ecc[11] = (uint8_t) (ecc_tmp >> 24); | 504 | ecc[11] = (uint8_t) (ecc_tmp >> 24); |
501 | 505 | ||
502 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, STS)); | 506 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS)); |
503 | ecc[12] = (uint8_t) (ecc_tmp >> 16); | 507 | ecc[12] = (uint8_t) (ecc_tmp >> 16); |
504 | 508 | ||
505 | return 0; | 509 | return 0; |
@@ -519,7 +523,7 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, | |||
519 | uint32_t bank = host->bank; | 523 | uint32_t bank = host->bank; |
520 | uint32_t ecc_tmp; | 524 | uint32_t ecc_tmp; |
521 | 525 | ||
522 | ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1)); | 526 | ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); |
523 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | 527 | ecc[0] = (uint8_t) (ecc_tmp >> 0); |
524 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | 528 | ecc[1] = (uint8_t) (ecc_tmp >> 8); |
525 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | 529 | ecc[2] = (uint8_t) (ecc_tmp >> 16); |
@@ -601,7 +605,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, | |||
601 | dma_async_issue_pending(chan); | 605 | dma_async_issue_pending(chan); |
602 | 606 | ||
603 | ret = | 607 | ret = |
604 | wait_for_completion_interruptible_timeout(&host->dma_access_complete, | 608 | wait_for_completion_timeout(&host->dma_access_complete, |
605 | msecs_to_jiffies(3000)); | 609 | msecs_to_jiffies(3000)); |
606 | if (ret <= 0) { | 610 | if (ret <= 0) { |
607 | chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); | 611 | chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); |
@@ -628,10 +632,10 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
628 | uint32_t *p = (uint32_t *)buf; | 632 | uint32_t *p = (uint32_t *)buf; |
629 | len = len >> 2; | 633 | len = len >> 2; |
630 | for (i = 0; i < len; i++) | 634 | for (i = 0; i < len; i++) |
631 | writel(p[i], chip->IO_ADDR_W); | 635 | writel_relaxed(p[i], chip->IO_ADDR_W); |
632 | } else { | 636 | } else { |
633 | for (i = 0; i < len; i++) | 637 | for (i = 0; i < len; i++) |
634 | writeb(buf[i], chip->IO_ADDR_W); | 638 | writeb_relaxed(buf[i], chip->IO_ADDR_W); |
635 | } | 639 | } |
636 | } | 640 | } |
637 | 641 | ||
@@ -651,10 +655,10 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
651 | uint32_t *p = (uint32_t *)buf; | 655 | uint32_t *p = (uint32_t *)buf; |
652 | len = len >> 2; | 656 | len = len >> 2; |
653 | for (i = 0; i < len; i++) | 657 | for (i = 0; i < len; i++) |
654 | p[i] = readl(chip->IO_ADDR_R); | 658 | p[i] = readl_relaxed(chip->IO_ADDR_R); |
655 | } else { | 659 | } else { |
656 | for (i = 0; i < len; i++) | 660 | for (i = 0; i < len; i++) |
657 | buf[i] = readb(chip->IO_ADDR_R); | 661 | buf[i] = readb_relaxed(chip->IO_ADDR_R); |
658 | } | 662 | } |
659 | } | 663 | } |
660 | 664 | ||
@@ -783,7 +787,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, | |||
783 | uint32_t num_err, i; | 787 | uint32_t num_err, i; |
784 | uint32_t ecc1, ecc2, ecc3, ecc4; | 788 | uint32_t ecc1, ecc2, ecc3, ecc4; |
785 | 789 | ||
786 | num_err = (readl(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF; | 790 | num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF; |
787 | 791 | ||
788 | /* no bit flipping */ | 792 | /* no bit flipping */ |
789 | if (likely(num_err == 0)) | 793 | if (likely(num_err == 0)) |
@@ -826,10 +830,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, | |||
826 | * uint64_t array and error offset indexes are populated in err_idx | 830 | * uint64_t array and error offset indexes are populated in err_idx |
827 | * array | 831 | * array |
828 | */ | 832 | */ |
829 | ecc1 = readl(FSMC_NAND_REG(regs, bank, ECC1)); | 833 | ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1)); |
830 | ecc2 = readl(FSMC_NAND_REG(regs, bank, ECC2)); | 834 | ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2)); |
831 | ecc3 = readl(FSMC_NAND_REG(regs, bank, ECC3)); | 835 | ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3)); |
832 | ecc4 = readl(FSMC_NAND_REG(regs, bank, STS)); | 836 | ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS)); |
833 | 837 | ||
834 | err_idx[0] = (ecc1 >> 0) & 0x1FFF; | 838 | err_idx[0] = (ecc1 >> 0) & 0x1FFF; |
835 | err_idx[1] = (ecc1 >> 13) & 0x1FFF; | 839 | err_idx[1] = (ecc1 >> 13) & 0x1FFF; |
@@ -860,7 +864,7 @@ static bool filter(struct dma_chan *chan, void *slave) | |||
860 | } | 864 | } |
861 | 865 | ||
862 | #ifdef CONFIG_OF | 866 | #ifdef CONFIG_OF |
863 | static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev, | 867 | static int fsmc_nand_probe_config_dt(struct platform_device *pdev, |
864 | struct device_node *np) | 868 | struct device_node *np) |
865 | { | 869 | { |
866 | struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); | 870 | struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); |
@@ -876,15 +880,13 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev, | |||
876 | return -EINVAL; | 880 | return -EINVAL; |
877 | } | 881 | } |
878 | } | 882 | } |
879 | of_property_read_u32(np, "st,ale-off", &pdata->ale_off); | ||
880 | of_property_read_u32(np, "st,cle-off", &pdata->cle_off); | ||
881 | if (of_get_property(np, "nand-skip-bbtscan", NULL)) | 883 | if (of_get_property(np, "nand-skip-bbtscan", NULL)) |
882 | pdata->options = NAND_SKIP_BBTSCAN; | 884 | pdata->options = NAND_SKIP_BBTSCAN; |
883 | 885 | ||
884 | return 0; | 886 | return 0; |
885 | } | 887 | } |
886 | #else | 888 | #else |
887 | static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev, | 889 | static int fsmc_nand_probe_config_dt(struct platform_device *pdev, |
888 | struct device_node *np) | 890 | struct device_node *np) |
889 | { | 891 | { |
890 | return -ENOSYS; | 892 | return -ENOSYS; |
@@ -935,41 +937,28 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
935 | if (!res) | 937 | if (!res) |
936 | return -EINVAL; | 938 | return -EINVAL; |
937 | 939 | ||
938 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | 940 | host->data_va = devm_request_and_ioremap(&pdev->dev, res); |
939 | pdev->name)) { | ||
940 | dev_err(&pdev->dev, "Failed to get memory data resourse\n"); | ||
941 | return -ENOENT; | ||
942 | } | ||
943 | |||
944 | host->data_pa = (dma_addr_t)res->start; | ||
945 | host->data_va = devm_ioremap(&pdev->dev, res->start, | ||
946 | resource_size(res)); | ||
947 | if (!host->data_va) { | 941 | if (!host->data_va) { |
948 | dev_err(&pdev->dev, "data ioremap failed\n"); | 942 | dev_err(&pdev->dev, "data ioremap failed\n"); |
949 | return -ENOMEM; | 943 | return -ENOMEM; |
950 | } | 944 | } |
945 | host->data_pa = (dma_addr_t)res->start; | ||
951 | 946 | ||
952 | if (!devm_request_mem_region(&pdev->dev, res->start + pdata->ale_off, | 947 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr"); |
953 | resource_size(res), pdev->name)) { | 948 | if (!res) |
954 | dev_err(&pdev->dev, "Failed to get memory ale resourse\n"); | 949 | return -EINVAL; |
955 | return -ENOENT; | ||
956 | } | ||
957 | 950 | ||
958 | host->addr_va = devm_ioremap(&pdev->dev, res->start + pdata->ale_off, | 951 | host->addr_va = devm_request_and_ioremap(&pdev->dev, res); |
959 | resource_size(res)); | ||
960 | if (!host->addr_va) { | 952 | if (!host->addr_va) { |
961 | dev_err(&pdev->dev, "ale ioremap failed\n"); | 953 | dev_err(&pdev->dev, "ale ioremap failed\n"); |
962 | return -ENOMEM; | 954 | return -ENOMEM; |
963 | } | 955 | } |
964 | 956 | ||
965 | if (!devm_request_mem_region(&pdev->dev, res->start + pdata->cle_off, | 957 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd"); |
966 | resource_size(res), pdev->name)) { | 958 | if (!res) |
967 | dev_err(&pdev->dev, "Failed to get memory cle resourse\n"); | 959 | return -EINVAL; |
968 | return -ENOENT; | ||
969 | } | ||
970 | 960 | ||
971 | host->cmd_va = devm_ioremap(&pdev->dev, res->start + pdata->cle_off, | 961 | host->cmd_va = devm_request_and_ioremap(&pdev->dev, res); |
972 | resource_size(res)); | ||
973 | if (!host->cmd_va) { | 962 | if (!host->cmd_va) { |
974 | dev_err(&pdev->dev, "ale ioremap failed\n"); | 963 | dev_err(&pdev->dev, "ale ioremap failed\n"); |
975 | return -ENOMEM; | 964 | return -ENOMEM; |
@@ -979,14 +968,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
979 | if (!res) | 968 | if (!res) |
980 | return -EINVAL; | 969 | return -EINVAL; |
981 | 970 | ||
982 | if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), | 971 | host->regs_va = devm_request_and_ioremap(&pdev->dev, res); |
983 | pdev->name)) { | ||
984 | dev_err(&pdev->dev, "Failed to get memory regs resourse\n"); | ||
985 | return -ENOENT; | ||
986 | } | ||
987 | |||
988 | host->regs_va = devm_ioremap(&pdev->dev, res->start, | ||
989 | resource_size(res)); | ||
990 | if (!host->regs_va) { | 972 | if (!host->regs_va) { |
991 | dev_err(&pdev->dev, "regs ioremap failed\n"); | 973 | dev_err(&pdev->dev, "regs ioremap failed\n"); |
992 | return -ENOMEM; | 974 | return -ENOMEM; |
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index bc73bc5f2713..e789e3f51710 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c | |||
@@ -90,14 +90,14 @@ static void gpio_nand_writebuf(struct mtd_info *mtd, const u_char *buf, int len) | |||
90 | { | 90 | { |
91 | struct nand_chip *this = mtd->priv; | 91 | struct nand_chip *this = mtd->priv; |
92 | 92 | ||
93 | writesb(this->IO_ADDR_W, buf, len); | 93 | iowrite8_rep(this->IO_ADDR_W, buf, len); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len) | 96 | static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len) |
97 | { | 97 | { |
98 | struct nand_chip *this = mtd->priv; | 98 | struct nand_chip *this = mtd->priv; |
99 | 99 | ||
100 | readsb(this->IO_ADDR_R, buf, len); | 100 | ioread8_rep(this->IO_ADDR_R, buf, len); |
101 | } | 101 | } |
102 | 102 | ||
103 | static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf, | 103 | static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf, |
@@ -106,7 +106,7 @@ static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf, | |||
106 | struct nand_chip *this = mtd->priv; | 106 | struct nand_chip *this = mtd->priv; |
107 | 107 | ||
108 | if (IS_ALIGNED((unsigned long)buf, 2)) { | 108 | if (IS_ALIGNED((unsigned long)buf, 2)) { |
109 | writesw(this->IO_ADDR_W, buf, len>>1); | 109 | iowrite16_rep(this->IO_ADDR_W, buf, len>>1); |
110 | } else { | 110 | } else { |
111 | int i; | 111 | int i; |
112 | unsigned short *ptr = (unsigned short *)buf; | 112 | unsigned short *ptr = (unsigned short *)buf; |
@@ -121,7 +121,7 @@ static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len) | |||
121 | struct nand_chip *this = mtd->priv; | 121 | struct nand_chip *this = mtd->priv; |
122 | 122 | ||
123 | if (IS_ALIGNED((unsigned long)buf, 2)) { | 123 | if (IS_ALIGNED((unsigned long)buf, 2)) { |
124 | readsw(this->IO_ADDR_R, buf, len>>1); | 124 | ioread16_rep(this->IO_ADDR_R, buf, len>>1); |
125 | } else { | 125 | } else { |
126 | int i; | 126 | int i; |
127 | unsigned short *ptr = (unsigned short *)buf; | 127 | unsigned short *ptr = (unsigned short *)buf; |
@@ -134,7 +134,11 @@ static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len) | |||
134 | static int gpio_nand_devready(struct mtd_info *mtd) | 134 | static int gpio_nand_devready(struct mtd_info *mtd) |
135 | { | 135 | { |
136 | struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); | 136 | struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); |
137 | return gpio_get_value(gpiomtd->plat.gpio_rdy); | 137 | |
138 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) | ||
139 | return gpio_get_value(gpiomtd->plat.gpio_rdy); | ||
140 | |||
141 | return 1; | ||
138 | } | 142 | } |
139 | 143 | ||
140 | #ifdef CONFIG_OF | 144 | #ifdef CONFIG_OF |
@@ -227,7 +231,7 @@ gpio_nand_get_io_sync(struct platform_device *pdev) | |||
227 | return platform_get_resource(pdev, IORESOURCE_MEM, 1); | 231 | return platform_get_resource(pdev, IORESOURCE_MEM, 1); |
228 | } | 232 | } |
229 | 233 | ||
230 | static int __devexit gpio_nand_remove(struct platform_device *dev) | 234 | static int gpio_nand_remove(struct platform_device *dev) |
231 | { | 235 | { |
232 | struct gpiomtd *gpiomtd = platform_get_drvdata(dev); | 236 | struct gpiomtd *gpiomtd = platform_get_drvdata(dev); |
233 | struct resource *res; | 237 | struct resource *res; |
@@ -252,7 +256,8 @@ static int __devexit gpio_nand_remove(struct platform_device *dev) | |||
252 | gpio_free(gpiomtd->plat.gpio_nce); | 256 | gpio_free(gpiomtd->plat.gpio_nce); |
253 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) | 257 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) |
254 | gpio_free(gpiomtd->plat.gpio_nwp); | 258 | gpio_free(gpiomtd->plat.gpio_nwp); |
255 | gpio_free(gpiomtd->plat.gpio_rdy); | 259 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) |
260 | gpio_free(gpiomtd->plat.gpio_rdy); | ||
256 | 261 | ||
257 | kfree(gpiomtd); | 262 | kfree(gpiomtd); |
258 | 263 | ||
@@ -277,7 +282,7 @@ static void __iomem *request_and_remap(struct resource *res, size_t size, | |||
277 | return ptr; | 282 | return ptr; |
278 | } | 283 | } |
279 | 284 | ||
280 | static int __devinit gpio_nand_probe(struct platform_device *dev) | 285 | static int gpio_nand_probe(struct platform_device *dev) |
281 | { | 286 | { |
282 | struct gpiomtd *gpiomtd; | 287 | struct gpiomtd *gpiomtd; |
283 | struct nand_chip *this; | 288 | struct nand_chip *this; |
@@ -336,10 +341,12 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) | |||
336 | if (ret) | 341 | if (ret) |
337 | goto err_cle; | 342 | goto err_cle; |
338 | gpio_direction_output(gpiomtd->plat.gpio_cle, 0); | 343 | gpio_direction_output(gpiomtd->plat.gpio_cle, 0); |
339 | ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY"); | 344 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) { |
340 | if (ret) | 345 | ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY"); |
341 | goto err_rdy; | 346 | if (ret) |
342 | gpio_direction_input(gpiomtd->plat.gpio_rdy); | 347 | goto err_rdy; |
348 | gpio_direction_input(gpiomtd->plat.gpio_rdy); | ||
349 | } | ||
343 | 350 | ||
344 | 351 | ||
345 | this->IO_ADDR_W = this->IO_ADDR_R; | 352 | this->IO_ADDR_W = this->IO_ADDR_R; |
@@ -386,7 +393,8 @@ static int __devinit gpio_nand_probe(struct platform_device *dev) | |||
386 | err_wp: | 393 | err_wp: |
387 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) | 394 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) |
388 | gpio_set_value(gpiomtd->plat.gpio_nwp, 0); | 395 | gpio_set_value(gpiomtd->plat.gpio_nwp, 0); |
389 | gpio_free(gpiomtd->plat.gpio_rdy); | 396 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) |
397 | gpio_free(gpiomtd->plat.gpio_rdy); | ||
390 | err_rdy: | 398 | err_rdy: |
391 | gpio_free(gpiomtd->plat.gpio_cle); | 399 | gpio_free(gpiomtd->plat.gpio_cle); |
392 | err_cle: | 400 | err_cle: |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 3502accd4bc3..d84699c7968e 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c | |||
@@ -18,7 +18,6 @@ | |||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | 18 | * with this program; if not, write to the Free Software Foundation, Inc., |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
20 | */ | 20 | */ |
21 | #include <linux/mtd/gpmi-nand.h> | ||
22 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
23 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
24 | 23 | ||
@@ -166,6 +165,15 @@ int gpmi_init(struct gpmi_nand_data *this) | |||
166 | if (ret) | 165 | if (ret) |
167 | goto err_out; | 166 | goto err_out; |
168 | 167 | ||
168 | /* | ||
169 | * Reset BCH here, too. We got failures otherwise :( | ||
170 | * See later BCH reset for explanation of MX23 handling | ||
171 | */ | ||
172 | ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); | ||
173 | if (ret) | ||
174 | goto err_out; | ||
175 | |||
176 | |||
169 | /* Choose NAND mode. */ | 177 | /* Choose NAND mode. */ |
170 | writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); | 178 | writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); |
171 | 179 | ||
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index d79696b2f19b..5cd141f7bfc2 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/mtd/gpmi-nand.h> | ||
29 | #include <linux/mtd/partitions.h> | 28 | #include <linux/mtd/partitions.h> |
30 | #include <linux/pinctrl/consumer.h> | 29 | #include <linux/pinctrl/consumer.h> |
31 | #include <linux/of.h> | 30 | #include <linux/of.h> |
@@ -33,6 +32,12 @@ | |||
33 | #include <linux/of_mtd.h> | 32 | #include <linux/of_mtd.h> |
34 | #include "gpmi-nand.h" | 33 | #include "gpmi-nand.h" |
35 | 34 | ||
35 | /* Resource names for the GPMI NAND driver. */ | ||
36 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" | ||
37 | #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch" | ||
38 | #define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch" | ||
39 | #define GPMI_NAND_DMA_INTERRUPT_RES_NAME "gpmi-dma" | ||
40 | |||
36 | /* add our owner bbt descriptor */ | 41 | /* add our owner bbt descriptor */ |
37 | static uint8_t scan_ff_pattern[] = { 0xff }; | 42 | static uint8_t scan_ff_pattern[] = { 0xff }; |
38 | static struct nand_bbt_descr gpmi_bbt_descr = { | 43 | static struct nand_bbt_descr gpmi_bbt_descr = { |
@@ -222,7 +227,7 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr) | |||
222 | 227 | ||
223 | ret = dma_map_sg(this->dev, sgl, 1, dr); | 228 | ret = dma_map_sg(this->dev, sgl, 1, dr); |
224 | if (ret == 0) | 229 | if (ret == 0) |
225 | pr_err("map failed.\n"); | 230 | pr_err("DMA mapping failed.\n"); |
226 | 231 | ||
227 | this->direct_dma_map_ok = false; | 232 | this->direct_dma_map_ok = false; |
228 | } | 233 | } |
@@ -314,7 +319,7 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this, | |||
314 | return 0; | 319 | return 0; |
315 | } | 320 | } |
316 | 321 | ||
317 | static int __devinit | 322 | static int |
318 | acquire_register_block(struct gpmi_nand_data *this, const char *res_name) | 323 | acquire_register_block(struct gpmi_nand_data *this, const char *res_name) |
319 | { | 324 | { |
320 | struct platform_device *pdev = this->pdev; | 325 | struct platform_device *pdev = this->pdev; |
@@ -355,7 +360,7 @@ static void release_register_block(struct gpmi_nand_data *this) | |||
355 | res->bch_regs = NULL; | 360 | res->bch_regs = NULL; |
356 | } | 361 | } |
357 | 362 | ||
358 | static int __devinit | 363 | static int |
359 | acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h) | 364 | acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h) |
360 | { | 365 | { |
361 | struct platform_device *pdev = this->pdev; | 366 | struct platform_device *pdev = this->pdev; |
@@ -422,7 +427,7 @@ static void release_dma_channels(struct gpmi_nand_data *this) | |||
422 | } | 427 | } |
423 | } | 428 | } |
424 | 429 | ||
425 | static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) | 430 | static int acquire_dma_channels(struct gpmi_nand_data *this) |
426 | { | 431 | { |
427 | struct platform_device *pdev = this->pdev; | 432 | struct platform_device *pdev = this->pdev; |
428 | struct resource *r_dma; | 433 | struct resource *r_dma; |
@@ -456,7 +461,7 @@ static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) | |||
456 | 461 | ||
457 | dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); | 462 | dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); |
458 | if (!dma_chan) { | 463 | if (!dma_chan) { |
459 | pr_err("dma_request_channel failed.\n"); | 464 | pr_err("Failed to request DMA channel.\n"); |
460 | goto acquire_err; | 465 | goto acquire_err; |
461 | } | 466 | } |
462 | 467 | ||
@@ -487,7 +492,7 @@ static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = { | |||
487 | "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch", | 492 | "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch", |
488 | }; | 493 | }; |
489 | 494 | ||
490 | static int __devinit gpmi_get_clks(struct gpmi_nand_data *this) | 495 | static int gpmi_get_clks(struct gpmi_nand_data *this) |
491 | { | 496 | { |
492 | struct resources *r = &this->resources; | 497 | struct resources *r = &this->resources; |
493 | char **extra_clks = NULL; | 498 | char **extra_clks = NULL; |
@@ -533,7 +538,7 @@ err_clock: | |||
533 | return -ENOMEM; | 538 | return -ENOMEM; |
534 | } | 539 | } |
535 | 540 | ||
536 | static int __devinit acquire_resources(struct gpmi_nand_data *this) | 541 | static int acquire_resources(struct gpmi_nand_data *this) |
537 | { | 542 | { |
538 | struct pinctrl *pinctrl; | 543 | struct pinctrl *pinctrl; |
539 | int ret; | 544 | int ret; |
@@ -583,7 +588,7 @@ static void release_resources(struct gpmi_nand_data *this) | |||
583 | release_dma_channels(this); | 588 | release_dma_channels(this); |
584 | } | 589 | } |
585 | 590 | ||
586 | static int __devinit init_hardware(struct gpmi_nand_data *this) | 591 | static int init_hardware(struct gpmi_nand_data *this) |
587 | { | 592 | { |
588 | int ret; | 593 | int ret; |
589 | 594 | ||
@@ -625,7 +630,8 @@ static int read_page_prepare(struct gpmi_nand_data *this, | |||
625 | length, DMA_FROM_DEVICE); | 630 | length, DMA_FROM_DEVICE); |
626 | if (dma_mapping_error(dev, dest_phys)) { | 631 | if (dma_mapping_error(dev, dest_phys)) { |
627 | if (alt_size < length) { | 632 | if (alt_size < length) { |
628 | pr_err("Alternate buffer is too small\n"); | 633 | pr_err("%s, Alternate buffer is too small\n", |
634 | __func__); | ||
629 | return -ENOMEM; | 635 | return -ENOMEM; |
630 | } | 636 | } |
631 | goto map_failed; | 637 | goto map_failed; |
@@ -675,7 +681,8 @@ static int send_page_prepare(struct gpmi_nand_data *this, | |||
675 | DMA_TO_DEVICE); | 681 | DMA_TO_DEVICE); |
676 | if (dma_mapping_error(dev, source_phys)) { | 682 | if (dma_mapping_error(dev, source_phys)) { |
677 | if (alt_size < length) { | 683 | if (alt_size < length) { |
678 | pr_err("Alternate buffer is too small\n"); | 684 | pr_err("%s, Alternate buffer is too small\n", |
685 | __func__); | ||
679 | return -ENOMEM; | 686 | return -ENOMEM; |
680 | } | 687 | } |
681 | goto map_failed; | 688 | goto map_failed; |
@@ -763,7 +770,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) | |||
763 | 770 | ||
764 | error_alloc: | 771 | error_alloc: |
765 | gpmi_free_dma_buffer(this); | 772 | gpmi_free_dma_buffer(this); |
766 | pr_err("allocate DMA buffer ret!!\n"); | 773 | pr_err("Error allocating DMA buffers!\n"); |
767 | return -ENOMEM; | 774 | return -ENOMEM; |
768 | } | 775 | } |
769 | 776 | ||
@@ -1474,7 +1481,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this) | |||
1474 | /* Set up the NFC geometry which is used by BCH. */ | 1481 | /* Set up the NFC geometry which is used by BCH. */ |
1475 | ret = bch_set_geometry(this); | 1482 | ret = bch_set_geometry(this); |
1476 | if (ret) { | 1483 | if (ret) { |
1477 | pr_err("set geometry ret : %d\n", ret); | 1484 | pr_err("Error setting BCH geometry : %d\n", ret); |
1478 | return ret; | 1485 | return ret; |
1479 | } | 1486 | } |
1480 | 1487 | ||
@@ -1535,7 +1542,7 @@ static void gpmi_nfc_exit(struct gpmi_nand_data *this) | |||
1535 | gpmi_free_dma_buffer(this); | 1542 | gpmi_free_dma_buffer(this); |
1536 | } | 1543 | } |
1537 | 1544 | ||
1538 | static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) | 1545 | static int gpmi_nfc_init(struct gpmi_nand_data *this) |
1539 | { | 1546 | { |
1540 | struct mtd_info *mtd = &this->mtd; | 1547 | struct mtd_info *mtd = &this->mtd; |
1541 | struct nand_chip *chip = &this->nand; | 1548 | struct nand_chip *chip = &this->nand; |
@@ -1618,7 +1625,7 @@ static const struct of_device_id gpmi_nand_id_table[] = { | |||
1618 | }; | 1625 | }; |
1619 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); | 1626 | MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); |
1620 | 1627 | ||
1621 | static int __devinit gpmi_nand_probe(struct platform_device *pdev) | 1628 | static int gpmi_nand_probe(struct platform_device *pdev) |
1622 | { | 1629 | { |
1623 | struct gpmi_nand_data *this; | 1630 | struct gpmi_nand_data *this; |
1624 | const struct of_device_id *of_id; | 1631 | const struct of_device_id *of_id; |
@@ -1668,7 +1675,7 @@ exit_acquire_resources: | |||
1668 | return ret; | 1675 | return ret; |
1669 | } | 1676 | } |
1670 | 1677 | ||
1671 | static int __devexit gpmi_nand_remove(struct platform_device *pdev) | 1678 | static int gpmi_nand_remove(struct platform_device *pdev) |
1672 | { | 1679 | { |
1673 | struct gpmi_nand_data *this = platform_get_drvdata(pdev); | 1680 | struct gpmi_nand_data *this = platform_get_drvdata(pdev); |
1674 | 1681 | ||
@@ -1685,7 +1692,7 @@ static struct platform_driver gpmi_nand_driver = { | |||
1685 | .of_match_table = gpmi_nand_id_table, | 1692 | .of_match_table = gpmi_nand_id_table, |
1686 | }, | 1693 | }, |
1687 | .probe = gpmi_nand_probe, | 1694 | .probe = gpmi_nand_probe, |
1688 | .remove = __devexit_p(gpmi_nand_remove), | 1695 | .remove = gpmi_nand_remove, |
1689 | .id_table = gpmi_ids, | 1696 | .id_table = gpmi_ids, |
1690 | }; | 1697 | }; |
1691 | module_platform_driver(gpmi_nand_driver); | 1698 | module_platform_driver(gpmi_nand_driver); |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index 7ac25c1e58f9..3d93a5e39090 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h | |||
@@ -130,7 +130,6 @@ struct gpmi_nand_data { | |||
130 | /* System Interface */ | 130 | /* System Interface */ |
131 | struct device *dev; | 131 | struct device *dev; |
132 | struct platform_device *pdev; | 132 | struct platform_device *pdev; |
133 | struct gpmi_nand_platform_data *pdata; | ||
134 | 133 | ||
135 | /* Resources */ | 134 | /* Resources */ |
136 | struct resources resources; | 135 | struct resources resources; |
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index 100b6775e175..8d415f014e1d 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
@@ -316,13 +316,17 @@ err: | |||
316 | return ret; | 316 | return ret; |
317 | } | 317 | } |
318 | 318 | ||
319 | static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base) | 319 | static inline void jz_nand_iounmap_resource(struct resource *res, |
320 | void __iomem *base) | ||
320 | { | 321 | { |
321 | iounmap(base); | 322 | iounmap(base); |
322 | release_mem_region(res->start, resource_size(res)); | 323 | release_mem_region(res->start, resource_size(res)); |
323 | } | 324 | } |
324 | 325 | ||
325 | static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) { | 326 | static int jz_nand_detect_bank(struct platform_device *pdev, |
327 | struct jz_nand *nand, unsigned char bank, | ||
328 | size_t chipnr, uint8_t *nand_maf_id, | ||
329 | uint8_t *nand_dev_id) { | ||
326 | int ret; | 330 | int ret; |
327 | int gpio; | 331 | int gpio; |
328 | char gpio_name[9]; | 332 | char gpio_name[9]; |
@@ -400,7 +404,7 @@ notfound_gpio: | |||
400 | return ret; | 404 | return ret; |
401 | } | 405 | } |
402 | 406 | ||
403 | static int __devinit jz_nand_probe(struct platform_device *pdev) | 407 | static int jz_nand_probe(struct platform_device *pdev) |
404 | { | 408 | { |
405 | int ret; | 409 | int ret; |
406 | struct jz_nand *nand; | 410 | struct jz_nand *nand; |
@@ -541,7 +545,7 @@ err_free: | |||
541 | return ret; | 545 | return ret; |
542 | } | 546 | } |
543 | 547 | ||
544 | static int __devexit jz_nand_remove(struct platform_device *pdev) | 548 | static int jz_nand_remove(struct platform_device *pdev) |
545 | { | 549 | { |
546 | struct jz_nand *nand = platform_get_drvdata(pdev); | 550 | struct jz_nand *nand = platform_get_drvdata(pdev); |
547 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; | 551 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; |
@@ -573,7 +577,7 @@ static int __devexit jz_nand_remove(struct platform_device *pdev) | |||
573 | 577 | ||
574 | static struct platform_driver jz_nand_driver = { | 578 | static struct platform_driver jz_nand_driver = { |
575 | .probe = jz_nand_probe, | 579 | .probe = jz_nand_probe, |
576 | .remove = __devexit_p(jz_nand_remove), | 580 | .remove = jz_nand_remove, |
577 | .driver = { | 581 | .driver = { |
578 | .name = "jz4740-nand", | 582 | .name = "jz4740-nand", |
579 | .owner = THIS_MODULE, | 583 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index c29b7ac1f6af..f182befa7360 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c | |||
@@ -655,7 +655,7 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev) | |||
655 | /* | 655 | /* |
656 | * Probe for NAND controller | 656 | * Probe for NAND controller |
657 | */ | 657 | */ |
658 | static int __devinit lpc32xx_nand_probe(struct platform_device *pdev) | 658 | static int lpc32xx_nand_probe(struct platform_device *pdev) |
659 | { | 659 | { |
660 | struct lpc32xx_nand_host *host; | 660 | struct lpc32xx_nand_host *host; |
661 | struct mtd_info *mtd; | 661 | struct mtd_info *mtd; |
@@ -845,7 +845,7 @@ err_exit1: | |||
845 | /* | 845 | /* |
846 | * Remove NAND device | 846 | * Remove NAND device |
847 | */ | 847 | */ |
848 | static int __devexit lpc32xx_nand_remove(struct platform_device *pdev) | 848 | static int lpc32xx_nand_remove(struct platform_device *pdev) |
849 | { | 849 | { |
850 | struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); | 850 | struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); |
851 | struct mtd_info *mtd = &host->mtd; | 851 | struct mtd_info *mtd = &host->mtd; |
@@ -907,7 +907,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match); | |||
907 | 907 | ||
908 | static struct platform_driver lpc32xx_nand_driver = { | 908 | static struct platform_driver lpc32xx_nand_driver = { |
909 | .probe = lpc32xx_nand_probe, | 909 | .probe = lpc32xx_nand_probe, |
910 | .remove = __devexit_p(lpc32xx_nand_remove), | 910 | .remove = lpc32xx_nand_remove, |
911 | .resume = lpc32xx_nand_resume, | 911 | .resume = lpc32xx_nand_resume, |
912 | .suspend = lpc32xx_nand_suspend, | 912 | .suspend = lpc32xx_nand_suspend, |
913 | .driver = { | 913 | .driver = { |
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index 32409c45d479..030b78c62895 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c | |||
@@ -755,7 +755,7 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev) | |||
755 | /* | 755 | /* |
756 | * Probe for NAND controller | 756 | * Probe for NAND controller |
757 | */ | 757 | */ |
758 | static int __devinit lpc32xx_nand_probe(struct platform_device *pdev) | 758 | static int lpc32xx_nand_probe(struct platform_device *pdev) |
759 | { | 759 | { |
760 | struct lpc32xx_nand_host *host; | 760 | struct lpc32xx_nand_host *host; |
761 | struct mtd_info *mtd; | 761 | struct mtd_info *mtd; |
@@ -949,7 +949,7 @@ err_exit1: | |||
949 | /* | 949 | /* |
950 | * Remove NAND device. | 950 | * Remove NAND device. |
951 | */ | 951 | */ |
952 | static int __devexit lpc32xx_nand_remove(struct platform_device *pdev) | 952 | static int lpc32xx_nand_remove(struct platform_device *pdev) |
953 | { | 953 | { |
954 | uint32_t tmp; | 954 | uint32_t tmp; |
955 | struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); | 955 | struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); |
@@ -1021,7 +1021,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match); | |||
1021 | 1021 | ||
1022 | static struct platform_driver lpc32xx_nand_driver = { | 1022 | static struct platform_driver lpc32xx_nand_driver = { |
1023 | .probe = lpc32xx_nand_probe, | 1023 | .probe = lpc32xx_nand_probe, |
1024 | .remove = __devexit_p(lpc32xx_nand_remove), | 1024 | .remove = lpc32xx_nand_remove, |
1025 | .resume = lpc32xx_nand_resume, | 1025 | .resume = lpc32xx_nand_resume, |
1026 | .suspend = lpc32xx_nand_suspend, | 1026 | .suspend = lpc32xx_nand_suspend, |
1027 | .driver = { | 1027 | .driver = { |
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index f776c8577b8c..3c9cdcbc4cba 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -626,7 +626,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) | |||
626 | iounmap(prv->csreg); | 626 | iounmap(prv->csreg); |
627 | } | 627 | } |
628 | 628 | ||
629 | static int __devinit mpc5121_nfc_probe(struct platform_device *op) | 629 | static int mpc5121_nfc_probe(struct platform_device *op) |
630 | { | 630 | { |
631 | struct device_node *rootnode, *dn = op->dev.of_node; | 631 | struct device_node *rootnode, *dn = op->dev.of_node; |
632 | struct device *dev = &op->dev; | 632 | struct device *dev = &op->dev; |
@@ -827,7 +827,7 @@ error: | |||
827 | return retval; | 827 | return retval; |
828 | } | 828 | } |
829 | 829 | ||
830 | static int __devexit mpc5121_nfc_remove(struct platform_device *op) | 830 | static int mpc5121_nfc_remove(struct platform_device *op) |
831 | { | 831 | { |
832 | struct device *dev = &op->dev; | 832 | struct device *dev = &op->dev; |
833 | struct mtd_info *mtd = dev_get_drvdata(dev); | 833 | struct mtd_info *mtd = dev_get_drvdata(dev); |
@@ -841,14 +841,14 @@ static int __devexit mpc5121_nfc_remove(struct platform_device *op) | |||
841 | return 0; | 841 | return 0; |
842 | } | 842 | } |
843 | 843 | ||
844 | static struct of_device_id mpc5121_nfc_match[] __devinitdata = { | 844 | static struct of_device_id mpc5121_nfc_match[] = { |
845 | { .compatible = "fsl,mpc5121-nfc", }, | 845 | { .compatible = "fsl,mpc5121-nfc", }, |
846 | {}, | 846 | {}, |
847 | }; | 847 | }; |
848 | 848 | ||
849 | static struct platform_driver mpc5121_nfc_driver = { | 849 | static struct platform_driver mpc5121_nfc_driver = { |
850 | .probe = mpc5121_nfc_probe, | 850 | .probe = mpc5121_nfc_probe, |
851 | .remove = __devexit_p(mpc5121_nfc_remove), | 851 | .remove = mpc5121_nfc_remove, |
852 | .driver = { | 852 | .driver = { |
853 | .name = DRV_NAME, | 853 | .name = DRV_NAME, |
854 | .owner = THIS_MODULE, | 854 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 022dcdc256fb..45204e41a028 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -266,7 +266,8 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { | |||
266 | } | 266 | } |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL }; | 269 | static const char const *part_probes[] = { |
270 | "cmdlinepart", "RedBoot", "ofpart", NULL }; | ||
270 | 271 | ||
271 | static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) | 272 | static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) |
272 | { | 273 | { |
@@ -1378,7 +1379,7 @@ static int __init mxcnd_probe_dt(struct mxc_nand_host *host) | |||
1378 | } | 1379 | } |
1379 | #endif | 1380 | #endif |
1380 | 1381 | ||
1381 | static int __devinit mxcnd_probe(struct platform_device *pdev) | 1382 | static int mxcnd_probe(struct platform_device *pdev) |
1382 | { | 1383 | { |
1383 | struct nand_chip *this; | 1384 | struct nand_chip *this; |
1384 | struct mtd_info *mtd; | 1385 | struct mtd_info *mtd; |
@@ -1556,12 +1557,13 @@ static int __devinit mxcnd_probe(struct platform_device *pdev) | |||
1556 | return 0; | 1557 | return 0; |
1557 | 1558 | ||
1558 | escan: | 1559 | escan: |
1559 | clk_disable_unprepare(host->clk); | 1560 | if (host->clk_act) |
1561 | clk_disable_unprepare(host->clk); | ||
1560 | 1562 | ||
1561 | return err; | 1563 | return err; |
1562 | } | 1564 | } |
1563 | 1565 | ||
1564 | static int __devexit mxcnd_remove(struct platform_device *pdev) | 1566 | static int mxcnd_remove(struct platform_device *pdev) |
1565 | { | 1567 | { |
1566 | struct mxc_nand_host *host = platform_get_drvdata(pdev); | 1568 | struct mxc_nand_host *host = platform_get_drvdata(pdev); |
1567 | 1569 | ||
@@ -1580,7 +1582,7 @@ static struct platform_driver mxcnd_driver = { | |||
1580 | }, | 1582 | }, |
1581 | .id_table = mxcnd_devtype, | 1583 | .id_table = mxcnd_devtype, |
1582 | .probe = mxcnd_probe, | 1584 | .probe = mxcnd_probe, |
1583 | .remove = __devexit_p(mxcnd_remove), | 1585 | .remove = mxcnd_remove, |
1584 | }; | 1586 | }; |
1585 | module_platform_driver(mxcnd_driver); | 1587 | module_platform_driver(mxcnd_driver); |
1586 | 1588 | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 1a03b7f673ce..8323ac991ad1 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -93,8 +93,7 @@ static struct nand_ecclayout nand_oob_128 = { | |||
93 | .length = 78} } | 93 | .length = 78} } |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, | 96 | static int nand_get_device(struct mtd_info *mtd, int new_state); |
97 | int new_state); | ||
98 | 97 | ||
99 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | 98 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, |
100 | struct mtd_oob_ops *ops); | 99 | struct mtd_oob_ops *ops); |
@@ -130,15 +129,12 @@ static int check_offs_len(struct mtd_info *mtd, | |||
130 | * nand_release_device - [GENERIC] release chip | 129 | * nand_release_device - [GENERIC] release chip |
131 | * @mtd: MTD device structure | 130 | * @mtd: MTD device structure |
132 | * | 131 | * |
133 | * Deselect, release chip lock and wake up anyone waiting on the device. | 132 | * Release chip lock and wake up anyone waiting on the device. |
134 | */ | 133 | */ |
135 | static void nand_release_device(struct mtd_info *mtd) | 134 | static void nand_release_device(struct mtd_info *mtd) |
136 | { | 135 | { |
137 | struct nand_chip *chip = mtd->priv; | 136 | struct nand_chip *chip = mtd->priv; |
138 | 137 | ||
139 | /* De-select the NAND device */ | ||
140 | chip->select_chip(mtd, -1); | ||
141 | |||
142 | /* Release the controller and the chip */ | 138 | /* Release the controller and the chip */ |
143 | spin_lock(&chip->controller->lock); | 139 | spin_lock(&chip->controller->lock); |
144 | chip->controller->active = NULL; | 140 | chip->controller->active = NULL; |
@@ -160,7 +156,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd) | |||
160 | } | 156 | } |
161 | 157 | ||
162 | /** | 158 | /** |
163 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip | 159 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip |
164 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip | 160 | * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip |
165 | * @mtd: MTD device structure | 161 | * @mtd: MTD device structure |
166 | * | 162 | * |
@@ -303,7 +299,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
303 | if (getchip) { | 299 | if (getchip) { |
304 | chipnr = (int)(ofs >> chip->chip_shift); | 300 | chipnr = (int)(ofs >> chip->chip_shift); |
305 | 301 | ||
306 | nand_get_device(chip, mtd, FL_READING); | 302 | nand_get_device(mtd, FL_READING); |
307 | 303 | ||
308 | /* Select the NAND device */ | 304 | /* Select the NAND device */ |
309 | chip->select_chip(mtd, chipnr); | 305 | chip->select_chip(mtd, chipnr); |
@@ -333,8 +329,10 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
333 | i++; | 329 | i++; |
334 | } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); | 330 | } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); |
335 | 331 | ||
336 | if (getchip) | 332 | if (getchip) { |
333 | chip->select_chip(mtd, -1); | ||
337 | nand_release_device(mtd); | 334 | nand_release_device(mtd); |
335 | } | ||
338 | 336 | ||
339 | return res; | 337 | return res; |
340 | } | 338 | } |
@@ -383,7 +381,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
383 | struct mtd_oob_ops ops; | 381 | struct mtd_oob_ops ops; |
384 | loff_t wr_ofs = ofs; | 382 | loff_t wr_ofs = ofs; |
385 | 383 | ||
386 | nand_get_device(chip, mtd, FL_WRITING); | 384 | nand_get_device(mtd, FL_WRITING); |
387 | 385 | ||
388 | ops.datbuf = NULL; | 386 | ops.datbuf = NULL; |
389 | ops.oobbuf = buf; | 387 | ops.oobbuf = buf; |
@@ -492,7 +490,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) | |||
492 | void nand_wait_ready(struct mtd_info *mtd) | 490 | void nand_wait_ready(struct mtd_info *mtd) |
493 | { | 491 | { |
494 | struct nand_chip *chip = mtd->priv; | 492 | struct nand_chip *chip = mtd->priv; |
495 | unsigned long timeo = jiffies + 2; | 493 | unsigned long timeo = jiffies + msecs_to_jiffies(20); |
496 | 494 | ||
497 | /* 400ms timeout */ | 495 | /* 400ms timeout */ |
498 | if (in_interrupt() || oops_in_progress) | 496 | if (in_interrupt() || oops_in_progress) |
@@ -750,15 +748,15 @@ static void panic_nand_get_device(struct nand_chip *chip, | |||
750 | 748 | ||
751 | /** | 749 | /** |
752 | * nand_get_device - [GENERIC] Get chip for selected access | 750 | * nand_get_device - [GENERIC] Get chip for selected access |
753 | * @chip: the nand chip descriptor | ||
754 | * @mtd: MTD device structure | 751 | * @mtd: MTD device structure |
755 | * @new_state: the state which is requested | 752 | * @new_state: the state which is requested |
756 | * | 753 | * |
757 | * Get the device and lock it for exclusive access | 754 | * Get the device and lock it for exclusive access |
758 | */ | 755 | */ |
759 | static int | 756 | static int |
760 | nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) | 757 | nand_get_device(struct mtd_info *mtd, int new_state) |
761 | { | 758 | { |
759 | struct nand_chip *chip = mtd->priv; | ||
762 | spinlock_t *lock = &chip->controller->lock; | 760 | spinlock_t *lock = &chip->controller->lock; |
763 | wait_queue_head_t *wq = &chip->controller->wq; | 761 | wait_queue_head_t *wq = &chip->controller->wq; |
764 | DECLARE_WAITQUEUE(wait, current); | 762 | DECLARE_WAITQUEUE(wait, current); |
@@ -865,6 +863,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
865 | led_trigger_event(nand_led_trigger, LED_OFF); | 863 | led_trigger_event(nand_led_trigger, LED_OFF); |
866 | 864 | ||
867 | status = (int)chip->read_byte(mtd); | 865 | status = (int)chip->read_byte(mtd); |
866 | /* This can happen if in case of timeout or buggy dev_ready */ | ||
867 | WARN_ON(!(status & NAND_STATUS_READY)); | ||
868 | return status; | 868 | return status; |
869 | } | 869 | } |
870 | 870 | ||
@@ -899,7 +899,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, | |||
899 | /* Call wait ready function */ | 899 | /* Call wait ready function */ |
900 | status = chip->waitfunc(mtd, chip); | 900 | status = chip->waitfunc(mtd, chip); |
901 | /* See if device thinks it succeeded */ | 901 | /* See if device thinks it succeeded */ |
902 | if (status & 0x01) { | 902 | if (status & NAND_STATUS_FAIL) { |
903 | pr_debug("%s: error status = 0x%08x\n", | 903 | pr_debug("%s: error status = 0x%08x\n", |
904 | __func__, status); | 904 | __func__, status); |
905 | ret = -EIO; | 905 | ret = -EIO; |
@@ -932,7 +932,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
932 | if (ofs + len == mtd->size) | 932 | if (ofs + len == mtd->size) |
933 | len -= mtd->erasesize; | 933 | len -= mtd->erasesize; |
934 | 934 | ||
935 | nand_get_device(chip, mtd, FL_UNLOCKING); | 935 | nand_get_device(mtd, FL_UNLOCKING); |
936 | 936 | ||
937 | /* Shift to get chip number */ | 937 | /* Shift to get chip number */ |
938 | chipnr = ofs >> chip->chip_shift; | 938 | chipnr = ofs >> chip->chip_shift; |
@@ -950,6 +950,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
950 | ret = __nand_unlock(mtd, ofs, len, 0); | 950 | ret = __nand_unlock(mtd, ofs, len, 0); |
951 | 951 | ||
952 | out: | 952 | out: |
953 | chip->select_chip(mtd, -1); | ||
953 | nand_release_device(mtd); | 954 | nand_release_device(mtd); |
954 | 955 | ||
955 | return ret; | 956 | return ret; |
@@ -981,7 +982,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
981 | if (check_offs_len(mtd, ofs, len)) | 982 | if (check_offs_len(mtd, ofs, len)) |
982 | ret = -EINVAL; | 983 | ret = -EINVAL; |
983 | 984 | ||
984 | nand_get_device(chip, mtd, FL_LOCKING); | 985 | nand_get_device(mtd, FL_LOCKING); |
985 | 986 | ||
986 | /* Shift to get chip number */ | 987 | /* Shift to get chip number */ |
987 | chipnr = ofs >> chip->chip_shift; | 988 | chipnr = ofs >> chip->chip_shift; |
@@ -1004,7 +1005,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
1004 | /* Call wait ready function */ | 1005 | /* Call wait ready function */ |
1005 | status = chip->waitfunc(mtd, chip); | 1006 | status = chip->waitfunc(mtd, chip); |
1006 | /* See if device thinks it succeeded */ | 1007 | /* See if device thinks it succeeded */ |
1007 | if (status & 0x01) { | 1008 | if (status & NAND_STATUS_FAIL) { |
1008 | pr_debug("%s: error status = 0x%08x\n", | 1009 | pr_debug("%s: error status = 0x%08x\n", |
1009 | __func__, status); | 1010 | __func__, status); |
1010 | ret = -EIO; | 1011 | ret = -EIO; |
@@ -1014,6 +1015,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
1014 | ret = __nand_unlock(mtd, ofs, len, 0x1); | 1015 | ret = __nand_unlock(mtd, ofs, len, 0x1); |
1015 | 1016 | ||
1016 | out: | 1017 | out: |
1018 | chip->select_chip(mtd, -1); | ||
1017 | nand_release_device(mtd); | 1019 | nand_release_device(mtd); |
1018 | 1020 | ||
1019 | return ret; | 1021 | return ret; |
@@ -1550,6 +1552,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1550 | chip->select_chip(mtd, chipnr); | 1552 | chip->select_chip(mtd, chipnr); |
1551 | } | 1553 | } |
1552 | } | 1554 | } |
1555 | chip->select_chip(mtd, -1); | ||
1553 | 1556 | ||
1554 | ops->retlen = ops->len - (size_t) readlen; | 1557 | ops->retlen = ops->len - (size_t) readlen; |
1555 | if (oob) | 1558 | if (oob) |
@@ -1577,11 +1580,10 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1577 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | 1580 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, |
1578 | size_t *retlen, uint8_t *buf) | 1581 | size_t *retlen, uint8_t *buf) |
1579 | { | 1582 | { |
1580 | struct nand_chip *chip = mtd->priv; | ||
1581 | struct mtd_oob_ops ops; | 1583 | struct mtd_oob_ops ops; |
1582 | int ret; | 1584 | int ret; |
1583 | 1585 | ||
1584 | nand_get_device(chip, mtd, FL_READING); | 1586 | nand_get_device(mtd, FL_READING); |
1585 | ops.len = len; | 1587 | ops.len = len; |
1586 | ops.datbuf = buf; | 1588 | ops.datbuf = buf; |
1587 | ops.oobbuf = NULL; | 1589 | ops.oobbuf = NULL; |
@@ -1804,6 +1806,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1804 | chip->select_chip(mtd, chipnr); | 1806 | chip->select_chip(mtd, chipnr); |
1805 | } | 1807 | } |
1806 | } | 1808 | } |
1809 | chip->select_chip(mtd, -1); | ||
1807 | 1810 | ||
1808 | ops->oobretlen = ops->ooblen - readlen; | 1811 | ops->oobretlen = ops->ooblen - readlen; |
1809 | 1812 | ||
@@ -1827,7 +1830,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1827 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, | 1830 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, |
1828 | struct mtd_oob_ops *ops) | 1831 | struct mtd_oob_ops *ops) |
1829 | { | 1832 | { |
1830 | struct nand_chip *chip = mtd->priv; | ||
1831 | int ret = -ENOTSUPP; | 1833 | int ret = -ENOTSUPP; |
1832 | 1834 | ||
1833 | ops->retlen = 0; | 1835 | ops->retlen = 0; |
@@ -1839,7 +1841,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1839 | return -EINVAL; | 1841 | return -EINVAL; |
1840 | } | 1842 | } |
1841 | 1843 | ||
1842 | nand_get_device(chip, mtd, FL_READING); | 1844 | nand_get_device(mtd, FL_READING); |
1843 | 1845 | ||
1844 | switch (ops->mode) { | 1846 | switch (ops->mode) { |
1845 | case MTD_OPS_PLACE_OOB: | 1847 | case MTD_OPS_PLACE_OOB: |
@@ -2186,8 +2188,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2186 | chip->select_chip(mtd, chipnr); | 2188 | chip->select_chip(mtd, chipnr); |
2187 | 2189 | ||
2188 | /* Check, if it is write protected */ | 2190 | /* Check, if it is write protected */ |
2189 | if (nand_check_wp(mtd)) | 2191 | if (nand_check_wp(mtd)) { |
2190 | return -EIO; | 2192 | ret = -EIO; |
2193 | goto err_out; | ||
2194 | } | ||
2191 | 2195 | ||
2192 | realpage = (int)(to >> chip->page_shift); | 2196 | realpage = (int)(to >> chip->page_shift); |
2193 | page = realpage & chip->pagemask; | 2197 | page = realpage & chip->pagemask; |
@@ -2199,8 +2203,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2199 | chip->pagebuf = -1; | 2203 | chip->pagebuf = -1; |
2200 | 2204 | ||
2201 | /* Don't allow multipage oob writes with offset */ | 2205 | /* Don't allow multipage oob writes with offset */ |
2202 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) | 2206 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) { |
2203 | return -EINVAL; | 2207 | ret = -EINVAL; |
2208 | goto err_out; | ||
2209 | } | ||
2204 | 2210 | ||
2205 | while (1) { | 2211 | while (1) { |
2206 | int bytes = mtd->writesize; | 2212 | int bytes = mtd->writesize; |
@@ -2251,6 +2257,9 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2251 | ops->retlen = ops->len - writelen; | 2257 | ops->retlen = ops->len - writelen; |
2252 | if (unlikely(oob)) | 2258 | if (unlikely(oob)) |
2253 | ops->oobretlen = ops->ooblen; | 2259 | ops->oobretlen = ops->ooblen; |
2260 | |||
2261 | err_out: | ||
2262 | chip->select_chip(mtd, -1); | ||
2254 | return ret; | 2263 | return ret; |
2255 | } | 2264 | } |
2256 | 2265 | ||
@@ -2302,11 +2311,10 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
2302 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | 2311 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, |
2303 | size_t *retlen, const uint8_t *buf) | 2312 | size_t *retlen, const uint8_t *buf) |
2304 | { | 2313 | { |
2305 | struct nand_chip *chip = mtd->priv; | ||
2306 | struct mtd_oob_ops ops; | 2314 | struct mtd_oob_ops ops; |
2307 | int ret; | 2315 | int ret; |
2308 | 2316 | ||
2309 | nand_get_device(chip, mtd, FL_WRITING); | 2317 | nand_get_device(mtd, FL_WRITING); |
2310 | ops.len = len; | 2318 | ops.len = len; |
2311 | ops.datbuf = (uint8_t *)buf; | 2319 | ops.datbuf = (uint8_t *)buf; |
2312 | ops.oobbuf = NULL; | 2320 | ops.oobbuf = NULL; |
@@ -2377,8 +2385,10 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
2377 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | 2385 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); |
2378 | 2386 | ||
2379 | /* Check, if it is write protected */ | 2387 | /* Check, if it is write protected */ |
2380 | if (nand_check_wp(mtd)) | 2388 | if (nand_check_wp(mtd)) { |
2389 | chip->select_chip(mtd, -1); | ||
2381 | return -EROFS; | 2390 | return -EROFS; |
2391 | } | ||
2382 | 2392 | ||
2383 | /* Invalidate the page cache, if we write to the cached page */ | 2393 | /* Invalidate the page cache, if we write to the cached page */ |
2384 | if (page == chip->pagebuf) | 2394 | if (page == chip->pagebuf) |
@@ -2391,6 +2401,8 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
2391 | else | 2401 | else |
2392 | status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); | 2402 | status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); |
2393 | 2403 | ||
2404 | chip->select_chip(mtd, -1); | ||
2405 | |||
2394 | if (status) | 2406 | if (status) |
2395 | return status; | 2407 | return status; |
2396 | 2408 | ||
@@ -2408,7 +2420,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
2408 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, | 2420 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, |
2409 | struct mtd_oob_ops *ops) | 2421 | struct mtd_oob_ops *ops) |
2410 | { | 2422 | { |
2411 | struct nand_chip *chip = mtd->priv; | ||
2412 | int ret = -ENOTSUPP; | 2423 | int ret = -ENOTSUPP; |
2413 | 2424 | ||
2414 | ops->retlen = 0; | 2425 | ops->retlen = 0; |
@@ -2420,7 +2431,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2420 | return -EINVAL; | 2431 | return -EINVAL; |
2421 | } | 2432 | } |
2422 | 2433 | ||
2423 | nand_get_device(chip, mtd, FL_WRITING); | 2434 | nand_get_device(mtd, FL_WRITING); |
2424 | 2435 | ||
2425 | switch (ops->mode) { | 2436 | switch (ops->mode) { |
2426 | case MTD_OPS_PLACE_OOB: | 2437 | case MTD_OPS_PLACE_OOB: |
@@ -2513,7 +2524,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2513 | return -EINVAL; | 2524 | return -EINVAL; |
2514 | 2525 | ||
2515 | /* Grab the lock and see if the device is available */ | 2526 | /* Grab the lock and see if the device is available */ |
2516 | nand_get_device(chip, mtd, FL_ERASING); | 2527 | nand_get_device(mtd, FL_ERASING); |
2517 | 2528 | ||
2518 | /* Shift to get first page */ | 2529 | /* Shift to get first page */ |
2519 | page = (int)(instr->addr >> chip->page_shift); | 2530 | page = (int)(instr->addr >> chip->page_shift); |
@@ -2623,6 +2634,7 @@ erase_exit: | |||
2623 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; | 2634 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; |
2624 | 2635 | ||
2625 | /* Deselect and wake up anyone waiting on the device */ | 2636 | /* Deselect and wake up anyone waiting on the device */ |
2637 | chip->select_chip(mtd, -1); | ||
2626 | nand_release_device(mtd); | 2638 | nand_release_device(mtd); |
2627 | 2639 | ||
2628 | /* Do call back function */ | 2640 | /* Do call back function */ |
@@ -2658,12 +2670,10 @@ erase_exit: | |||
2658 | */ | 2670 | */ |
2659 | static void nand_sync(struct mtd_info *mtd) | 2671 | static void nand_sync(struct mtd_info *mtd) |
2660 | { | 2672 | { |
2661 | struct nand_chip *chip = mtd->priv; | ||
2662 | |||
2663 | pr_debug("%s: called\n", __func__); | 2673 | pr_debug("%s: called\n", __func__); |
2664 | 2674 | ||
2665 | /* Grab the lock and see if the device is available */ | 2675 | /* Grab the lock and see if the device is available */ |
2666 | nand_get_device(chip, mtd, FL_SYNCING); | 2676 | nand_get_device(mtd, FL_SYNCING); |
2667 | /* Release it and go back */ | 2677 | /* Release it and go back */ |
2668 | nand_release_device(mtd); | 2678 | nand_release_device(mtd); |
2669 | } | 2679 | } |
@@ -2749,9 +2759,7 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, | |||
2749 | */ | 2759 | */ |
2750 | static int nand_suspend(struct mtd_info *mtd) | 2760 | static int nand_suspend(struct mtd_info *mtd) |
2751 | { | 2761 | { |
2752 | struct nand_chip *chip = mtd->priv; | 2762 | return nand_get_device(mtd, FL_PM_SUSPENDED); |
2753 | |||
2754 | return nand_get_device(chip, mtd, FL_PM_SUSPENDED); | ||
2755 | } | 2763 | } |
2756 | 2764 | ||
2757 | /** | 2765 | /** |
@@ -2849,6 +2857,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2849 | int i; | 2857 | int i; |
2850 | int val; | 2858 | int val; |
2851 | 2859 | ||
2860 | /* ONFI need to be probed in 8 bits mode */ | ||
2861 | WARN_ON(chip->options & NAND_BUSWIDTH_16); | ||
2852 | /* Try ONFI for unknown chip or LP */ | 2862 | /* Try ONFI for unknown chip or LP */ |
2853 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); | 2863 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); |
2854 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || | 2864 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || |
@@ -2913,7 +2923,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2913 | * | 2923 | * |
2914 | * Check if an ID string is repeated within a given sequence of bytes at | 2924 | * Check if an ID string is repeated within a given sequence of bytes at |
2915 | * specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a | 2925 | * specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a |
2916 | * period of 2). This is a helper function for nand_id_len(). Returns non-zero | 2926 | * period of 3). This is a helper function for nand_id_len(). Returns non-zero |
2917 | * if the repetition has a period of @period; otherwise, returns zero. | 2927 | * if the repetition has a period of @period; otherwise, returns zero. |
2918 | */ | 2928 | */ |
2919 | static int nand_id_has_period(u8 *id_data, int arrlen, int period) | 2929 | static int nand_id_has_period(u8 *id_data, int arrlen, int period) |
@@ -3242,11 +3252,15 @@ ident_done: | |||
3242 | break; | 3252 | break; |
3243 | } | 3253 | } |
3244 | 3254 | ||
3245 | /* | 3255 | if (chip->options & NAND_BUSWIDTH_AUTO) { |
3246 | * Check, if buswidth is correct. Hardware drivers should set | 3256 | WARN_ON(chip->options & NAND_BUSWIDTH_16); |
3247 | * chip correct! | 3257 | chip->options |= busw; |
3248 | */ | 3258 | nand_set_defaults(chip, busw); |
3249 | if (busw != (chip->options & NAND_BUSWIDTH_16)) { | 3259 | } else if (busw != (chip->options & NAND_BUSWIDTH_16)) { |
3260 | /* | ||
3261 | * Check, if buswidth is correct. Hardware drivers should set | ||
3262 | * chip correct! | ||
3263 | */ | ||
3250 | pr_info("NAND device: Manufacturer ID:" | 3264 | pr_info("NAND device: Manufacturer ID:" |
3251 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, | 3265 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, |
3252 | *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); | 3266 | *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); |
@@ -3285,10 +3299,10 @@ ident_done: | |||
3285 | chip->cmdfunc = nand_command_lp; | 3299 | chip->cmdfunc = nand_command_lp; |
3286 | 3300 | ||
3287 | pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," | 3301 | pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," |
3288 | " page size: %d, OOB size: %d\n", | 3302 | " %dMiB, page size: %d, OOB size: %d\n", |
3289 | *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, | 3303 | *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, |
3290 | chip->onfi_version ? chip->onfi_params.model : type->name, | 3304 | chip->onfi_version ? chip->onfi_params.model : type->name, |
3291 | mtd->writesize, mtd->oobsize); | 3305 | (int)(chip->chipsize >> 20), mtd->writesize, mtd->oobsize); |
3292 | 3306 | ||
3293 | return type; | 3307 | return type; |
3294 | } | 3308 | } |
@@ -3327,6 +3341,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3327 | return PTR_ERR(type); | 3341 | return PTR_ERR(type); |
3328 | } | 3342 | } |
3329 | 3343 | ||
3344 | chip->select_chip(mtd, -1); | ||
3345 | |||
3330 | /* Check for a chip array */ | 3346 | /* Check for a chip array */ |
3331 | for (i = 1; i < maxchips; i++) { | 3347 | for (i = 1; i < maxchips; i++) { |
3332 | chip->select_chip(mtd, i); | 3348 | chip->select_chip(mtd, i); |
@@ -3336,8 +3352,11 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3336 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 3352 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
3337 | /* Read manufacturer and device IDs */ | 3353 | /* Read manufacturer and device IDs */ |
3338 | if (nand_maf_id != chip->read_byte(mtd) || | 3354 | if (nand_maf_id != chip->read_byte(mtd) || |
3339 | nand_dev_id != chip->read_byte(mtd)) | 3355 | nand_dev_id != chip->read_byte(mtd)) { |
3356 | chip->select_chip(mtd, -1); | ||
3340 | break; | 3357 | break; |
3358 | } | ||
3359 | chip->select_chip(mtd, -1); | ||
3341 | } | 3360 | } |
3342 | if (i > 1) | 3361 | if (i > 1) |
3343 | pr_info("%d NAND chips detected\n", i); | 3362 | pr_info("%d NAND chips detected\n", i); |
@@ -3596,9 +3615,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3596 | /* Initialize state */ | 3615 | /* Initialize state */ |
3597 | chip->state = FL_READY; | 3616 | chip->state = FL_READY; |
3598 | 3617 | ||
3599 | /* De-select the device */ | ||
3600 | chip->select_chip(mtd, -1); | ||
3601 | |||
3602 | /* Invalidate the pagebuffer reference */ | 3618 | /* Invalidate the pagebuffer reference */ |
3603 | chip->pagebuf = -1; | 3619 | chip->pagebuf = -1; |
3604 | 3620 | ||
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index c3c13e64a2f0..818b65c85d12 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -42,6 +42,8 @@ | |||
42 | #include <linux/sched.h> | 42 | #include <linux/sched.h> |
43 | #include <linux/fs.h> | 43 | #include <linux/fs.h> |
44 | #include <linux/pagemap.h> | 44 | #include <linux/pagemap.h> |
45 | #include <linux/seq_file.h> | ||
46 | #include <linux/debugfs.h> | ||
45 | 47 | ||
46 | /* Default simulator parameters values */ | 48 | /* Default simulator parameters values */ |
47 | #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ | 49 | #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ |
@@ -105,7 +107,6 @@ static char *weakblocks = NULL; | |||
105 | static char *weakpages = NULL; | 107 | static char *weakpages = NULL; |
106 | static unsigned int bitflips = 0; | 108 | static unsigned int bitflips = 0; |
107 | static char *gravepages = NULL; | 109 | static char *gravepages = NULL; |
108 | static unsigned int rptwear = 0; | ||
109 | static unsigned int overridesize = 0; | 110 | static unsigned int overridesize = 0; |
110 | static char *cache_file = NULL; | 111 | static char *cache_file = NULL; |
111 | static unsigned int bbt; | 112 | static unsigned int bbt; |
@@ -130,7 +131,6 @@ module_param(weakblocks, charp, 0400); | |||
130 | module_param(weakpages, charp, 0400); | 131 | module_param(weakpages, charp, 0400); |
131 | module_param(bitflips, uint, 0400); | 132 | module_param(bitflips, uint, 0400); |
132 | module_param(gravepages, charp, 0400); | 133 | module_param(gravepages, charp, 0400); |
133 | module_param(rptwear, uint, 0400); | ||
134 | module_param(overridesize, uint, 0400); | 134 | module_param(overridesize, uint, 0400); |
135 | module_param(cache_file, charp, 0400); | 135 | module_param(cache_file, charp, 0400); |
136 | module_param(bbt, uint, 0400); | 136 | module_param(bbt, uint, 0400); |
@@ -162,7 +162,6 @@ MODULE_PARM_DESC(bitflips, "Maximum number of random bit flips per page (z | |||
162 | MODULE_PARM_DESC(gravepages, "Pages that lose data [: maximum reads (defaults to 3)]" | 162 | MODULE_PARM_DESC(gravepages, "Pages that lose data [: maximum reads (defaults to 3)]" |
163 | " separated by commas e.g. 1401:2 means page 1401" | 163 | " separated by commas e.g. 1401:2 means page 1401" |
164 | " can be read only twice before failing"); | 164 | " can be read only twice before failing"); |
165 | MODULE_PARM_DESC(rptwear, "Number of erases between reporting wear, if not zero"); | ||
166 | MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. " | 165 | MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. " |
167 | "The size is specified in erase blocks and as the exponent of a power of two" | 166 | "The size is specified in erase blocks and as the exponent of a power of two" |
168 | " e.g. 5 means a size of 32 erase blocks"); | 167 | " e.g. 5 means a size of 32 erase blocks"); |
@@ -286,6 +285,11 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " | |||
286 | /* Maximum page cache pages needed to read or write a NAND page to the cache_file */ | 285 | /* Maximum page cache pages needed to read or write a NAND page to the cache_file */ |
287 | #define NS_MAX_HELD_PAGES 16 | 286 | #define NS_MAX_HELD_PAGES 16 |
288 | 287 | ||
288 | struct nandsim_debug_info { | ||
289 | struct dentry *dfs_root; | ||
290 | struct dentry *dfs_wear_report; | ||
291 | }; | ||
292 | |||
289 | /* | 293 | /* |
290 | * A union to represent flash memory contents and flash buffer. | 294 | * A union to represent flash memory contents and flash buffer. |
291 | */ | 295 | */ |
@@ -365,6 +369,8 @@ struct nandsim { | |||
365 | void *file_buf; | 369 | void *file_buf; |
366 | struct page *held_pages[NS_MAX_HELD_PAGES]; | 370 | struct page *held_pages[NS_MAX_HELD_PAGES]; |
367 | int held_cnt; | 371 | int held_cnt; |
372 | |||
373 | struct nandsim_debug_info dbg; | ||
368 | }; | 374 | }; |
369 | 375 | ||
370 | /* | 376 | /* |
@@ -442,11 +448,123 @@ static LIST_HEAD(grave_pages); | |||
442 | static unsigned long *erase_block_wear = NULL; | 448 | static unsigned long *erase_block_wear = NULL; |
443 | static unsigned int wear_eb_count = 0; | 449 | static unsigned int wear_eb_count = 0; |
444 | static unsigned long total_wear = 0; | 450 | static unsigned long total_wear = 0; |
445 | static unsigned int rptwear_cnt = 0; | ||
446 | 451 | ||
447 | /* MTD structure for NAND controller */ | 452 | /* MTD structure for NAND controller */ |
448 | static struct mtd_info *nsmtd; | 453 | static struct mtd_info *nsmtd; |
449 | 454 | ||
455 | static int nandsim_debugfs_show(struct seq_file *m, void *private) | ||
456 | { | ||
457 | unsigned long wmin = -1, wmax = 0, avg; | ||
458 | unsigned long deciles[10], decile_max[10], tot = 0; | ||
459 | unsigned int i; | ||
460 | |||
461 | /* Calc wear stats */ | ||
462 | for (i = 0; i < wear_eb_count; ++i) { | ||
463 | unsigned long wear = erase_block_wear[i]; | ||
464 | if (wear < wmin) | ||
465 | wmin = wear; | ||
466 | if (wear > wmax) | ||
467 | wmax = wear; | ||
468 | tot += wear; | ||
469 | } | ||
470 | |||
471 | for (i = 0; i < 9; ++i) { | ||
472 | deciles[i] = 0; | ||
473 | decile_max[i] = (wmax * (i + 1) + 5) / 10; | ||
474 | } | ||
475 | deciles[9] = 0; | ||
476 | decile_max[9] = wmax; | ||
477 | for (i = 0; i < wear_eb_count; ++i) { | ||
478 | int d; | ||
479 | unsigned long wear = erase_block_wear[i]; | ||
480 | for (d = 0; d < 10; ++d) | ||
481 | if (wear <= decile_max[d]) { | ||
482 | deciles[d] += 1; | ||
483 | break; | ||
484 | } | ||
485 | } | ||
486 | avg = tot / wear_eb_count; | ||
487 | |||
488 | /* Output wear report */ | ||
489 | seq_printf(m, "Total numbers of erases: %lu\n", tot); | ||
490 | seq_printf(m, "Number of erase blocks: %u\n", wear_eb_count); | ||
491 | seq_printf(m, "Average number of erases: %lu\n", avg); | ||
492 | seq_printf(m, "Maximum number of erases: %lu\n", wmax); | ||
493 | seq_printf(m, "Minimum number of erases: %lu\n", wmin); | ||
494 | for (i = 0; i < 10; ++i) { | ||
495 | unsigned long from = (i ? decile_max[i - 1] + 1 : 0); | ||
496 | if (from > decile_max[i]) | ||
497 | continue; | ||
498 | seq_printf(m, "Number of ebs with erase counts from %lu to %lu : %lu\n", | ||
499 | from, | ||
500 | decile_max[i], | ||
501 | deciles[i]); | ||
502 | } | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static int nandsim_debugfs_open(struct inode *inode, struct file *file) | ||
508 | { | ||
509 | return single_open(file, nandsim_debugfs_show, inode->i_private); | ||
510 | } | ||
511 | |||
512 | static const struct file_operations dfs_fops = { | ||
513 | .open = nandsim_debugfs_open, | ||
514 | .read = seq_read, | ||
515 | .llseek = seq_lseek, | ||
516 | .release = single_release, | ||
517 | }; | ||
518 | |||
519 | /** | ||
520 | * nandsim_debugfs_create - initialize debugfs | ||
521 | * @dev: nandsim device description object | ||
522 | * | ||
523 | * This function creates all debugfs files for UBI device @ubi. Returns zero in | ||
524 | * case of success and a negative error code in case of failure. | ||
525 | */ | ||
526 | static int nandsim_debugfs_create(struct nandsim *dev) | ||
527 | { | ||
528 | struct nandsim_debug_info *dbg = &dev->dbg; | ||
529 | struct dentry *dent; | ||
530 | int err; | ||
531 | |||
532 | if (!IS_ENABLED(CONFIG_DEBUG_FS)) | ||
533 | return 0; | ||
534 | |||
535 | dent = debugfs_create_dir("nandsim", NULL); | ||
536 | if (IS_ERR_OR_NULL(dent)) { | ||
537 | int err = dent ? -ENODEV : PTR_ERR(dent); | ||
538 | |||
539 | NS_ERR("cannot create \"nandsim\" debugfs directory, err %d\n", | ||
540 | err); | ||
541 | return err; | ||
542 | } | ||
543 | dbg->dfs_root = dent; | ||
544 | |||
545 | dent = debugfs_create_file("wear_report", S_IRUSR, | ||
546 | dbg->dfs_root, dev, &dfs_fops); | ||
547 | if (IS_ERR_OR_NULL(dent)) | ||
548 | goto out_remove; | ||
549 | dbg->dfs_wear_report = dent; | ||
550 | |||
551 | return 0; | ||
552 | |||
553 | out_remove: | ||
554 | debugfs_remove_recursive(dbg->dfs_root); | ||
555 | err = dent ? PTR_ERR(dent) : -ENODEV; | ||
556 | return err; | ||
557 | } | ||
558 | |||
559 | /** | ||
560 | * nandsim_debugfs_remove - destroy all debugfs files | ||
561 | */ | ||
562 | static void nandsim_debugfs_remove(struct nandsim *ns) | ||
563 | { | ||
564 | if (IS_ENABLED(CONFIG_DEBUG_FS)) | ||
565 | debugfs_remove_recursive(ns->dbg.dfs_root); | ||
566 | } | ||
567 | |||
450 | /* | 568 | /* |
451 | * Allocate array of page pointers, create slab allocation for an array | 569 | * Allocate array of page pointers, create slab allocation for an array |
452 | * and initialize the array by NULL pointers. | 570 | * and initialize the array by NULL pointers. |
@@ -911,8 +1029,6 @@ static int setup_wear_reporting(struct mtd_info *mtd) | |||
911 | { | 1029 | { |
912 | size_t mem; | 1030 | size_t mem; |
913 | 1031 | ||
914 | if (!rptwear) | ||
915 | return 0; | ||
916 | wear_eb_count = div_u64(mtd->size, mtd->erasesize); | 1032 | wear_eb_count = div_u64(mtd->size, mtd->erasesize); |
917 | mem = wear_eb_count * sizeof(unsigned long); | 1033 | mem = wear_eb_count * sizeof(unsigned long); |
918 | if (mem / sizeof(unsigned long) != wear_eb_count) { | 1034 | if (mem / sizeof(unsigned long) != wear_eb_count) { |
@@ -929,64 +1045,18 @@ static int setup_wear_reporting(struct mtd_info *mtd) | |||
929 | 1045 | ||
930 | static void update_wear(unsigned int erase_block_no) | 1046 | static void update_wear(unsigned int erase_block_no) |
931 | { | 1047 | { |
932 | unsigned long wmin = -1, wmax = 0, avg; | ||
933 | unsigned long deciles[10], decile_max[10], tot = 0; | ||
934 | unsigned int i; | ||
935 | |||
936 | if (!erase_block_wear) | 1048 | if (!erase_block_wear) |
937 | return; | 1049 | return; |
938 | total_wear += 1; | 1050 | total_wear += 1; |
1051 | /* | ||
1052 | * TODO: Notify this through a debugfs entry, | ||
1053 | * instead of showing an error message. | ||
1054 | */ | ||
939 | if (total_wear == 0) | 1055 | if (total_wear == 0) |
940 | NS_ERR("Erase counter total overflow\n"); | 1056 | NS_ERR("Erase counter total overflow\n"); |
941 | erase_block_wear[erase_block_no] += 1; | 1057 | erase_block_wear[erase_block_no] += 1; |
942 | if (erase_block_wear[erase_block_no] == 0) | 1058 | if (erase_block_wear[erase_block_no] == 0) |
943 | NS_ERR("Erase counter overflow for erase block %u\n", erase_block_no); | 1059 | NS_ERR("Erase counter overflow for erase block %u\n", erase_block_no); |
944 | rptwear_cnt += 1; | ||
945 | if (rptwear_cnt < rptwear) | ||
946 | return; | ||
947 | rptwear_cnt = 0; | ||
948 | /* Calc wear stats */ | ||
949 | for (i = 0; i < wear_eb_count; ++i) { | ||
950 | unsigned long wear = erase_block_wear[i]; | ||
951 | if (wear < wmin) | ||
952 | wmin = wear; | ||
953 | if (wear > wmax) | ||
954 | wmax = wear; | ||
955 | tot += wear; | ||
956 | } | ||
957 | for (i = 0; i < 9; ++i) { | ||
958 | deciles[i] = 0; | ||
959 | decile_max[i] = (wmax * (i + 1) + 5) / 10; | ||
960 | } | ||
961 | deciles[9] = 0; | ||
962 | decile_max[9] = wmax; | ||
963 | for (i = 0; i < wear_eb_count; ++i) { | ||
964 | int d; | ||
965 | unsigned long wear = erase_block_wear[i]; | ||
966 | for (d = 0; d < 10; ++d) | ||
967 | if (wear <= decile_max[d]) { | ||
968 | deciles[d] += 1; | ||
969 | break; | ||
970 | } | ||
971 | } | ||
972 | avg = tot / wear_eb_count; | ||
973 | /* Output wear report */ | ||
974 | NS_INFO("*** Wear Report ***\n"); | ||
975 | NS_INFO("Total numbers of erases: %lu\n", tot); | ||
976 | NS_INFO("Number of erase blocks: %u\n", wear_eb_count); | ||
977 | NS_INFO("Average number of erases: %lu\n", avg); | ||
978 | NS_INFO("Maximum number of erases: %lu\n", wmax); | ||
979 | NS_INFO("Minimum number of erases: %lu\n", wmin); | ||
980 | for (i = 0; i < 10; ++i) { | ||
981 | unsigned long from = (i ? decile_max[i - 1] + 1 : 0); | ||
982 | if (from > decile_max[i]) | ||
983 | continue; | ||
984 | NS_INFO("Number of ebs with erase counts from %lu to %lu : %lu\n", | ||
985 | from, | ||
986 | decile_max[i], | ||
987 | deciles[i]); | ||
988 | } | ||
989 | NS_INFO("*** End of Wear Report ***\n"); | ||
990 | } | 1060 | } |
991 | 1061 | ||
992 | /* | 1062 | /* |
@@ -2327,6 +2397,9 @@ static int __init ns_init_module(void) | |||
2327 | if ((retval = setup_wear_reporting(nsmtd)) != 0) | 2397 | if ((retval = setup_wear_reporting(nsmtd)) != 0) |
2328 | goto err_exit; | 2398 | goto err_exit; |
2329 | 2399 | ||
2400 | if ((retval = nandsim_debugfs_create(nand)) != 0) | ||
2401 | goto err_exit; | ||
2402 | |||
2330 | if ((retval = init_nandsim(nsmtd)) != 0) | 2403 | if ((retval = init_nandsim(nsmtd)) != 0) |
2331 | goto err_exit; | 2404 | goto err_exit; |
2332 | 2405 | ||
@@ -2366,6 +2439,7 @@ static void __exit ns_cleanup_module(void) | |||
2366 | struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv; | 2439 | struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv; |
2367 | int i; | 2440 | int i; |
2368 | 2441 | ||
2442 | nandsim_debugfs_remove(ns); | ||
2369 | free_nandsim(ns); /* Free nandsim private resources */ | 2443 | free_nandsim(ns); /* Free nandsim private resources */ |
2370 | nand_release(nsmtd); /* Unregister driver */ | 2444 | nand_release(nsmtd); /* Unregister driver */ |
2371 | for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) | 2445 | for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 5fd3f010e3ae..8e148f1478fd 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -197,7 +197,7 @@ err: | |||
197 | return ret; | 197 | return ret; |
198 | } | 198 | } |
199 | 199 | ||
200 | static int __devinit ndfc_probe(struct platform_device *ofdev) | 200 | static int ndfc_probe(struct platform_device *ofdev) |
201 | { | 201 | { |
202 | struct ndfc_controller *ndfc; | 202 | struct ndfc_controller *ndfc; |
203 | const __be32 *reg; | 203 | const __be32 *reg; |
@@ -256,7 +256,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev) | |||
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | static int __devexit ndfc_remove(struct platform_device *ofdev) | 259 | static int ndfc_remove(struct platform_device *ofdev) |
260 | { | 260 | { |
261 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); | 261 | struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); |
262 | 262 | ||
@@ -279,7 +279,7 @@ static struct platform_driver ndfc_driver = { | |||
279 | .of_match_table = ndfc_match, | 279 | .of_match_table = ndfc_match, |
280 | }, | 280 | }, |
281 | .probe = ndfc_probe, | 281 | .probe = ndfc_probe, |
282 | .remove = __devexit_p(ndfc_remove), | 282 | .remove = ndfc_remove, |
283 | }; | 283 | }; |
284 | 284 | ||
285 | module_platform_driver(ndfc_driver); | 285 | module_platform_driver(ndfc_driver); |
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c deleted file mode 100644 index 9ee0c4edfacf..000000000000 --- a/drivers/mtd/nand/nomadik_nand.c +++ /dev/null | |||
@@ -1,235 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/nomadik_nand.c | ||
3 | * | ||
4 | * Overview: | ||
5 | * Driver for on-board NAND flash on Nomadik Platforms | ||
6 | * | ||
7 | * Copyright © 2007 STMicroelectronics Pvt. Ltd. | ||
8 | * Author: Sachin Verma <sachin.verma@st.com> | ||
9 | * | ||
10 | * Copyright © 2009 Alessandro Rubini | ||
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 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/mtd/mtd.h> | ||
28 | #include <linux/mtd/nand.h> | ||
29 | #include <linux/mtd/nand_ecc.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/mtd/partitions.h> | ||
32 | #include <linux/io.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/platform_data/mtd-nomadik-nand.h> | ||
35 | #include <mach/fsmc.h> | ||
36 | |||
37 | #include <mtd/mtd-abi.h> | ||
38 | |||
39 | struct nomadik_nand_host { | ||
40 | struct mtd_info mtd; | ||
41 | struct nand_chip nand; | ||
42 | void __iomem *data_va; | ||
43 | void __iomem *cmd_va; | ||
44 | void __iomem *addr_va; | ||
45 | struct nand_bbt_descr *bbt_desc; | ||
46 | }; | ||
47 | |||
48 | static struct nand_ecclayout nomadik_ecc_layout = { | ||
49 | .eccbytes = 3 * 4, | ||
50 | .eccpos = { /* each subpage has 16 bytes: pos 2,3,4 hosts ECC */ | ||
51 | 0x02, 0x03, 0x04, | ||
52 | 0x12, 0x13, 0x14, | ||
53 | 0x22, 0x23, 0x24, | ||
54 | 0x32, 0x33, 0x34}, | ||
55 | /* let's keep bytes 5,6,7 for us, just in case we change ECC algo */ | ||
56 | .oobfree = { {0x08, 0x08}, {0x18, 0x08}, {0x28, 0x08}, {0x38, 0x08} }, | ||
57 | }; | ||
58 | |||
59 | static void nomadik_ecc_control(struct mtd_info *mtd, int mode) | ||
60 | { | ||
61 | /* No need to enable hw ecc, it's on by default */ | ||
62 | } | ||
63 | |||
64 | static void nomadik_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||
65 | { | ||
66 | struct nand_chip *nand = mtd->priv; | ||
67 | struct nomadik_nand_host *host = nand->priv; | ||
68 | |||
69 | if (cmd == NAND_CMD_NONE) | ||
70 | return; | ||
71 | |||
72 | if (ctrl & NAND_CLE) | ||
73 | writeb(cmd, host->cmd_va); | ||
74 | else | ||
75 | writeb(cmd, host->addr_va); | ||
76 | } | ||
77 | |||
78 | static int nomadik_nand_probe(struct platform_device *pdev) | ||
79 | { | ||
80 | struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data; | ||
81 | struct nomadik_nand_host *host; | ||
82 | struct mtd_info *mtd; | ||
83 | struct nand_chip *nand; | ||
84 | struct resource *res; | ||
85 | int ret = 0; | ||
86 | |||
87 | /* Allocate memory for the device structure (and zero it) */ | ||
88 | host = kzalloc(sizeof(struct nomadik_nand_host), GFP_KERNEL); | ||
89 | if (!host) { | ||
90 | dev_err(&pdev->dev, "Failed to allocate device structure.\n"); | ||
91 | return -ENOMEM; | ||
92 | } | ||
93 | |||
94 | /* Call the client's init function, if any */ | ||
95 | if (pdata->init) | ||
96 | ret = pdata->init(); | ||
97 | if (ret < 0) { | ||
98 | dev_err(&pdev->dev, "Init function failed\n"); | ||
99 | goto err; | ||
100 | } | ||
101 | |||
102 | /* ioremap three regions */ | ||
103 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr"); | ||
104 | if (!res) { | ||
105 | ret = -EIO; | ||
106 | goto err_unmap; | ||
107 | } | ||
108 | host->addr_va = ioremap(res->start, resource_size(res)); | ||
109 | |||
110 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data"); | ||
111 | if (!res) { | ||
112 | ret = -EIO; | ||
113 | goto err_unmap; | ||
114 | } | ||
115 | host->data_va = ioremap(res->start, resource_size(res)); | ||
116 | |||
117 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd"); | ||
118 | if (!res) { | ||
119 | ret = -EIO; | ||
120 | goto err_unmap; | ||
121 | } | ||
122 | host->cmd_va = ioremap(res->start, resource_size(res)); | ||
123 | |||
124 | if (!host->addr_va || !host->data_va || !host->cmd_va) { | ||
125 | ret = -ENOMEM; | ||
126 | goto err_unmap; | ||
127 | } | ||
128 | |||
129 | /* Link all private pointers */ | ||
130 | mtd = &host->mtd; | ||
131 | nand = &host->nand; | ||
132 | mtd->priv = nand; | ||
133 | nand->priv = host; | ||
134 | |||
135 | host->mtd.owner = THIS_MODULE; | ||
136 | nand->IO_ADDR_R = host->data_va; | ||
137 | nand->IO_ADDR_W = host->data_va; | ||
138 | nand->cmd_ctrl = nomadik_cmd_ctrl; | ||
139 | |||
140 | /* | ||
141 | * This stanza declares ECC_HW but uses soft routines. It's because | ||
142 | * HW claims to make the calculation but not the correction. However, | ||
143 | * I haven't managed to get the desired data out of it until now. | ||
144 | */ | ||
145 | nand->ecc.mode = NAND_ECC_SOFT; | ||
146 | nand->ecc.layout = &nomadik_ecc_layout; | ||
147 | nand->ecc.hwctl = nomadik_ecc_control; | ||
148 | nand->ecc.size = 512; | ||
149 | nand->ecc.bytes = 3; | ||
150 | |||
151 | nand->options = pdata->options; | ||
152 | |||
153 | /* | ||
154 | * Scan to find existence of the device | ||
155 | */ | ||
156 | if (nand_scan(&host->mtd, 1)) { | ||
157 | ret = -ENXIO; | ||
158 | goto err_unmap; | ||
159 | } | ||
160 | |||
161 | mtd_device_register(&host->mtd, pdata->parts, pdata->nparts); | ||
162 | |||
163 | platform_set_drvdata(pdev, host); | ||
164 | return 0; | ||
165 | |||
166 | err_unmap: | ||
167 | if (host->cmd_va) | ||
168 | iounmap(host->cmd_va); | ||
169 | if (host->data_va) | ||
170 | iounmap(host->data_va); | ||
171 | if (host->addr_va) | ||
172 | iounmap(host->addr_va); | ||
173 | err: | ||
174 | kfree(host); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Clean up routine | ||
180 | */ | ||
181 | static int nomadik_nand_remove(struct platform_device *pdev) | ||
182 | { | ||
183 | struct nomadik_nand_host *host = platform_get_drvdata(pdev); | ||
184 | struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data; | ||
185 | |||
186 | if (pdata->exit) | ||
187 | pdata->exit(); | ||
188 | |||
189 | if (host) { | ||
190 | nand_release(&host->mtd); | ||
191 | iounmap(host->cmd_va); | ||
192 | iounmap(host->data_va); | ||
193 | iounmap(host->addr_va); | ||
194 | kfree(host); | ||
195 | } | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int nomadik_nand_suspend(struct device *dev) | ||
200 | { | ||
201 | struct nomadik_nand_host *host = dev_get_drvdata(dev); | ||
202 | int ret = 0; | ||
203 | if (host) | ||
204 | ret = mtd_suspend(&host->mtd); | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static int nomadik_nand_resume(struct device *dev) | ||
209 | { | ||
210 | struct nomadik_nand_host *host = dev_get_drvdata(dev); | ||
211 | if (host) | ||
212 | mtd_resume(&host->mtd); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static const struct dev_pm_ops nomadik_nand_pm_ops = { | ||
217 | .suspend = nomadik_nand_suspend, | ||
218 | .resume = nomadik_nand_resume, | ||
219 | }; | ||
220 | |||
221 | static struct platform_driver nomadik_nand_driver = { | ||
222 | .probe = nomadik_nand_probe, | ||
223 | .remove = nomadik_nand_remove, | ||
224 | .driver = { | ||
225 | .owner = THIS_MODULE, | ||
226 | .name = "nomadik_nand", | ||
227 | .pm = &nomadik_nand_pm_ops, | ||
228 | }, | ||
229 | }; | ||
230 | |||
231 | module_platform_driver(nomadik_nand_driver); | ||
232 | |||
233 | MODULE_LICENSE("GPL"); | ||
234 | MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)"); | ||
235 | MODULE_DESCRIPTION("NAND driver for Nomadik Platform"); | ||
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 94dc46bc118c..a6191198d259 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c | |||
@@ -246,7 +246,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand) | |||
246 | spin_unlock(&nand->lock); | 246 | spin_unlock(&nand->lock); |
247 | } | 247 | } |
248 | 248 | ||
249 | static int __devinit nuc900_nand_probe(struct platform_device *pdev) | 249 | static int nuc900_nand_probe(struct platform_device *pdev) |
250 | { | 250 | { |
251 | struct nuc900_nand *nuc900_nand; | 251 | struct nuc900_nand *nuc900_nand; |
252 | struct nand_chip *chip; | 252 | struct nand_chip *chip; |
@@ -317,7 +317,7 @@ fail1: kfree(nuc900_nand); | |||
317 | return retval; | 317 | return retval; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int __devexit nuc900_nand_remove(struct platform_device *pdev) | 320 | static int nuc900_nand_remove(struct platform_device *pdev) |
321 | { | 321 | { |
322 | struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); | 322 | struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); |
323 | struct resource *res; | 323 | struct resource *res; |
@@ -340,7 +340,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev) | |||
340 | 340 | ||
341 | static struct platform_driver nuc900_nand_driver = { | 341 | static struct platform_driver nuc900_nand_driver = { |
342 | .probe = nuc900_nand_probe, | 342 | .probe = nuc900_nand_probe, |
343 | .remove = __devexit_p(nuc900_nand_remove), | 343 | .remove = nuc900_nand_remove, |
344 | .driver = { | 344 | .driver = { |
345 | .name = "nuc900-fmi", | 345 | .name = "nuc900-fmi", |
346 | .owner = THIS_MODULE, | 346 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 1f34ba104ef4..0002d5e94f0d 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -1323,7 +1323,7 @@ static void omap3_free_bch(struct mtd_info *mtd) | |||
1323 | } | 1323 | } |
1324 | #endif /* CONFIG_MTD_NAND_OMAP_BCH */ | 1324 | #endif /* CONFIG_MTD_NAND_OMAP_BCH */ |
1325 | 1325 | ||
1326 | static int __devinit omap_nand_probe(struct platform_device *pdev) | 1326 | static int omap_nand_probe(struct platform_device *pdev) |
1327 | { | 1327 | { |
1328 | struct omap_nand_info *info; | 1328 | struct omap_nand_info *info; |
1329 | struct omap_nand_platform_data *pdata; | 1329 | struct omap_nand_platform_data *pdata; |
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index aefaf8cd31ef..cd72b9299f6b 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -194,7 +194,7 @@ no_res: | |||
194 | return ret; | 194 | return ret; |
195 | } | 195 | } |
196 | 196 | ||
197 | static int __devexit orion_nand_remove(struct platform_device *pdev) | 197 | static int orion_nand_remove(struct platform_device *pdev) |
198 | { | 198 | { |
199 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 199 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
200 | struct nand_chip *nc = mtd->priv; | 200 | struct nand_chip *nc = mtd->priv; |
@@ -223,7 +223,7 @@ static struct of_device_id orion_nand_of_match_table[] = { | |||
223 | #endif | 223 | #endif |
224 | 224 | ||
225 | static struct platform_driver orion_nand_driver = { | 225 | static struct platform_driver orion_nand_driver = { |
226 | .remove = __devexit_p(orion_nand_remove), | 226 | .remove = orion_nand_remove, |
227 | .driver = { | 227 | .driver = { |
228 | .name = "orion_nand", | 228 | .name = "orion_nand", |
229 | .owner = THIS_MODULE, | 229 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 1440e51cedcc..5a67082c07ee 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c | |||
@@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd) | |||
89 | return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); | 89 | return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int __devinit pasemi_nand_probe(struct platform_device *ofdev) | 92 | static int pasemi_nand_probe(struct platform_device *ofdev) |
93 | { | 93 | { |
94 | struct pci_dev *pdev; | 94 | struct pci_dev *pdev; |
95 | struct device_node *np = ofdev->dev.of_node; | 95 | struct device_node *np = ofdev->dev.of_node; |
@@ -184,7 +184,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) | |||
184 | return err; | 184 | return err; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int __devexit pasemi_nand_remove(struct platform_device *ofdev) | 187 | static int pasemi_nand_remove(struct platform_device *ofdev) |
188 | { | 188 | { |
189 | struct nand_chip *chip; | 189 | struct nand_chip *chip; |
190 | 190 | ||
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index a47ee68a0cfa..c004566a9ad2 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -28,7 +28,7 @@ static const char *part_probe_types[] = { "cmdlinepart", NULL }; | |||
28 | /* | 28 | /* |
29 | * Probe for the NAND device. | 29 | * Probe for the NAND device. |
30 | */ | 30 | */ |
31 | static int __devinit plat_nand_probe(struct platform_device *pdev) | 31 | static int plat_nand_probe(struct platform_device *pdev) |
32 | { | 32 | { |
33 | struct platform_nand_data *pdata = pdev->dev.platform_data; | 33 | struct platform_nand_data *pdata = pdev->dev.platform_data; |
34 | struct mtd_part_parser_data ppdata; | 34 | struct mtd_part_parser_data ppdata; |
@@ -134,7 +134,7 @@ out_free: | |||
134 | /* | 134 | /* |
135 | * Remove a NAND device. | 135 | * Remove a NAND device. |
136 | */ | 136 | */ |
137 | static int __devexit plat_nand_remove(struct platform_device *pdev) | 137 | static int plat_nand_remove(struct platform_device *pdev) |
138 | { | 138 | { |
139 | struct plat_nand_data *data = platform_get_drvdata(pdev); | 139 | struct plat_nand_data *data = platform_get_drvdata(pdev); |
140 | struct platform_nand_data *pdata = pdev->dev.platform_data; | 140 | struct platform_nand_data *pdata = pdev->dev.platform_data; |
@@ -160,7 +160,7 @@ MODULE_DEVICE_TABLE(of, plat_nand_match); | |||
160 | 160 | ||
161 | static struct platform_driver plat_nand_driver = { | 161 | static struct platform_driver plat_nand_driver = { |
162 | .probe = plat_nand_probe, | 162 | .probe = plat_nand_probe, |
163 | .remove = __devexit_p(plat_nand_remove), | 163 | .remove = plat_nand_remove, |
164 | .driver = { | 164 | .driver = { |
165 | .name = "gen_nand", | 165 | .name = "gen_nand", |
166 | .owner = THIS_MODULE, | 166 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 79ded48e7427..df954b4dcba2 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -730,11 +730,14 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | |||
730 | struct s3c2410_nand_mtd *mtd, | 730 | struct s3c2410_nand_mtd *mtd, |
731 | struct s3c2410_nand_set *set) | 731 | struct s3c2410_nand_set *set) |
732 | { | 732 | { |
733 | if (set) | 733 | if (set) { |
734 | mtd->mtd.name = set->name; | 734 | mtd->mtd.name = set->name; |
735 | 735 | ||
736 | return mtd_device_parse_register(&mtd->mtd, NULL, NULL, | 736 | return mtd_device_parse_register(&mtd->mtd, NULL, NULL, |
737 | set->partitions, set->nr_partitions); | 737 | set->partitions, set->nr_partitions); |
738 | } | ||
739 | |||
740 | return -ENODEV; | ||
738 | } | 741 | } |
739 | 742 | ||
740 | /** | 743 | /** |
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index f48ac5d80bbf..57b3971c9c0a 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c | |||
@@ -23,11 +23,18 @@ | |||
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/completion.h> | ||
26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/dmaengine.h> | ||
29 | #include <linux/dma-mapping.h> | ||
27 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
28 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/of.h> | ||
33 | #include <linux/of_device.h> | ||
34 | #include <linux/of_mtd.h> | ||
29 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
30 | #include <linux/pm_runtime.h> | 36 | #include <linux/pm_runtime.h> |
37 | #include <linux/sh_dma.h> | ||
31 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
32 | #include <linux/string.h> | 39 | #include <linux/string.h> |
33 | 40 | ||
@@ -106,6 +113,84 @@ static void wait_completion(struct sh_flctl *flctl) | |||
106 | writeb(0x0, FLTRCR(flctl)); | 113 | writeb(0x0, FLTRCR(flctl)); |
107 | } | 114 | } |
108 | 115 | ||
116 | static void flctl_dma_complete(void *param) | ||
117 | { | ||
118 | struct sh_flctl *flctl = param; | ||
119 | |||
120 | complete(&flctl->dma_complete); | ||
121 | } | ||
122 | |||
123 | static void flctl_release_dma(struct sh_flctl *flctl) | ||
124 | { | ||
125 | if (flctl->chan_fifo0_rx) { | ||
126 | dma_release_channel(flctl->chan_fifo0_rx); | ||
127 | flctl->chan_fifo0_rx = NULL; | ||
128 | } | ||
129 | if (flctl->chan_fifo0_tx) { | ||
130 | dma_release_channel(flctl->chan_fifo0_tx); | ||
131 | flctl->chan_fifo0_tx = NULL; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void flctl_setup_dma(struct sh_flctl *flctl) | ||
136 | { | ||
137 | dma_cap_mask_t mask; | ||
138 | struct dma_slave_config cfg; | ||
139 | struct platform_device *pdev = flctl->pdev; | ||
140 | struct sh_flctl_platform_data *pdata = pdev->dev.platform_data; | ||
141 | int ret; | ||
142 | |||
143 | if (!pdata) | ||
144 | return; | ||
145 | |||
146 | if (pdata->slave_id_fifo0_tx <= 0 || pdata->slave_id_fifo0_rx <= 0) | ||
147 | return; | ||
148 | |||
149 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | ||
150 | dma_cap_zero(mask); | ||
151 | dma_cap_set(DMA_SLAVE, mask); | ||
152 | |||
153 | flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter, | ||
154 | (void *)pdata->slave_id_fifo0_tx); | ||
155 | dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__, | ||
156 | flctl->chan_fifo0_tx); | ||
157 | |||
158 | if (!flctl->chan_fifo0_tx) | ||
159 | return; | ||
160 | |||
161 | memset(&cfg, 0, sizeof(cfg)); | ||
162 | cfg.slave_id = pdata->slave_id_fifo0_tx; | ||
163 | cfg.direction = DMA_MEM_TO_DEV; | ||
164 | cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl); | ||
165 | cfg.src_addr = 0; | ||
166 | ret = dmaengine_slave_config(flctl->chan_fifo0_tx, &cfg); | ||
167 | if (ret < 0) | ||
168 | goto err; | ||
169 | |||
170 | flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter, | ||
171 | (void *)pdata->slave_id_fifo0_rx); | ||
172 | dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__, | ||
173 | flctl->chan_fifo0_rx); | ||
174 | |||
175 | if (!flctl->chan_fifo0_rx) | ||
176 | goto err; | ||
177 | |||
178 | cfg.slave_id = pdata->slave_id_fifo0_rx; | ||
179 | cfg.direction = DMA_DEV_TO_MEM; | ||
180 | cfg.dst_addr = 0; | ||
181 | cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl); | ||
182 | ret = dmaengine_slave_config(flctl->chan_fifo0_rx, &cfg); | ||
183 | if (ret < 0) | ||
184 | goto err; | ||
185 | |||
186 | init_completion(&flctl->dma_complete); | ||
187 | |||
188 | return; | ||
189 | |||
190 | err: | ||
191 | flctl_release_dma(flctl); | ||
192 | } | ||
193 | |||
109 | static void set_addr(struct mtd_info *mtd, int column, int page_addr) | 194 | static void set_addr(struct mtd_info *mtd, int column, int page_addr) |
110 | { | 195 | { |
111 | struct sh_flctl *flctl = mtd_to_flctl(mtd); | 196 | struct sh_flctl *flctl = mtd_to_flctl(mtd); |
@@ -225,7 +310,7 @@ static enum flctl_ecc_res_t wait_recfifo_ready | |||
225 | 310 | ||
226 | for (i = 0; i < 3; i++) { | 311 | for (i = 0; i < 3; i++) { |
227 | uint8_t org; | 312 | uint8_t org; |
228 | int index; | 313 | unsigned int index; |
229 | 314 | ||
230 | data = readl(ecc_reg[i]); | 315 | data = readl(ecc_reg[i]); |
231 | 316 | ||
@@ -261,6 +346,70 @@ static void wait_wecfifo_ready(struct sh_flctl *flctl) | |||
261 | timeout_error(flctl, __func__); | 346 | timeout_error(flctl, __func__); |
262 | } | 347 | } |
263 | 348 | ||
349 | static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf, | ||
350 | int len, enum dma_data_direction dir) | ||
351 | { | ||
352 | struct dma_async_tx_descriptor *desc = NULL; | ||
353 | struct dma_chan *chan; | ||
354 | enum dma_transfer_direction tr_dir; | ||
355 | dma_addr_t dma_addr; | ||
356 | dma_cookie_t cookie = -EINVAL; | ||
357 | uint32_t reg; | ||
358 | int ret; | ||
359 | |||
360 | if (dir == DMA_FROM_DEVICE) { | ||
361 | chan = flctl->chan_fifo0_rx; | ||
362 | tr_dir = DMA_DEV_TO_MEM; | ||
363 | } else { | ||
364 | chan = flctl->chan_fifo0_tx; | ||
365 | tr_dir = DMA_MEM_TO_DEV; | ||
366 | } | ||
367 | |||
368 | dma_addr = dma_map_single(chan->device->dev, buf, len, dir); | ||
369 | |||
370 | if (dma_addr) | ||
371 | desc = dmaengine_prep_slave_single(chan, dma_addr, len, | ||
372 | tr_dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
373 | |||
374 | if (desc) { | ||
375 | reg = readl(FLINTDMACR(flctl)); | ||
376 | reg |= DREQ0EN; | ||
377 | writel(reg, FLINTDMACR(flctl)); | ||
378 | |||
379 | desc->callback = flctl_dma_complete; | ||
380 | desc->callback_param = flctl; | ||
381 | cookie = dmaengine_submit(desc); | ||
382 | |||
383 | dma_async_issue_pending(chan); | ||
384 | } else { | ||
385 | /* DMA failed, fall back to PIO */ | ||
386 | flctl_release_dma(flctl); | ||
387 | dev_warn(&flctl->pdev->dev, | ||
388 | "DMA failed, falling back to PIO\n"); | ||
389 | ret = -EIO; | ||
390 | goto out; | ||
391 | } | ||
392 | |||
393 | ret = | ||
394 | wait_for_completion_timeout(&flctl->dma_complete, | ||
395 | msecs_to_jiffies(3000)); | ||
396 | |||
397 | if (ret <= 0) { | ||
398 | chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); | ||
399 | dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n"); | ||
400 | } | ||
401 | |||
402 | out: | ||
403 | reg = readl(FLINTDMACR(flctl)); | ||
404 | reg &= ~DREQ0EN; | ||
405 | writel(reg, FLINTDMACR(flctl)); | ||
406 | |||
407 | dma_unmap_single(chan->device->dev, dma_addr, len, dir); | ||
408 | |||
409 | /* ret > 0 is success */ | ||
410 | return ret; | ||
411 | } | ||
412 | |||
264 | static void read_datareg(struct sh_flctl *flctl, int offset) | 413 | static void read_datareg(struct sh_flctl *flctl, int offset) |
265 | { | 414 | { |
266 | unsigned long data; | 415 | unsigned long data; |
@@ -279,11 +428,20 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset) | |||
279 | 428 | ||
280 | len_4align = (rlen + 3) / 4; | 429 | len_4align = (rlen + 3) / 4; |
281 | 430 | ||
431 | /* initiate DMA transfer */ | ||
432 | if (flctl->chan_fifo0_rx && rlen >= 32 && | ||
433 | flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0) | ||
434 | goto convert; /* DMA success */ | ||
435 | |||
436 | /* do polling transfer */ | ||
282 | for (i = 0; i < len_4align; i++) { | 437 | for (i = 0; i < len_4align; i++) { |
283 | wait_rfifo_ready(flctl); | 438 | wait_rfifo_ready(flctl); |
284 | buf[i] = readl(FLDTFIFO(flctl)); | 439 | buf[i] = readl(FLDTFIFO(flctl)); |
285 | buf[i] = be32_to_cpu(buf[i]); | ||
286 | } | 440 | } |
441 | |||
442 | convert: | ||
443 | for (i = 0; i < len_4align; i++) | ||
444 | buf[i] = be32_to_cpu(buf[i]); | ||
287 | } | 445 | } |
288 | 446 | ||
289 | static enum flctl_ecc_res_t read_ecfiforeg | 447 | static enum flctl_ecc_res_t read_ecfiforeg |
@@ -305,28 +463,39 @@ static enum flctl_ecc_res_t read_ecfiforeg | |||
305 | return res; | 463 | return res; |
306 | } | 464 | } |
307 | 465 | ||
308 | static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset) | 466 | static void write_fiforeg(struct sh_flctl *flctl, int rlen, |
467 | unsigned int offset) | ||
309 | { | 468 | { |
310 | int i, len_4align; | 469 | int i, len_4align; |
311 | unsigned long *data = (unsigned long *)&flctl->done_buff[offset]; | 470 | unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; |
312 | void *fifo_addr = (void *)FLDTFIFO(flctl); | ||
313 | 471 | ||
314 | len_4align = (rlen + 3) / 4; | 472 | len_4align = (rlen + 3) / 4; |
315 | for (i = 0; i < len_4align; i++) { | 473 | for (i = 0; i < len_4align; i++) { |
316 | wait_wfifo_ready(flctl); | 474 | wait_wfifo_ready(flctl); |
317 | writel(cpu_to_be32(data[i]), fifo_addr); | 475 | writel(cpu_to_be32(buf[i]), FLDTFIFO(flctl)); |
318 | } | 476 | } |
319 | } | 477 | } |
320 | 478 | ||
321 | static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, int offset) | 479 | static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, |
480 | unsigned int offset) | ||
322 | { | 481 | { |
323 | int i, len_4align; | 482 | int i, len_4align; |
324 | unsigned long *data = (unsigned long *)&flctl->done_buff[offset]; | 483 | unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; |
325 | 484 | ||
326 | len_4align = (rlen + 3) / 4; | 485 | len_4align = (rlen + 3) / 4; |
486 | |||
487 | for (i = 0; i < len_4align; i++) | ||
488 | buf[i] = cpu_to_be32(buf[i]); | ||
489 | |||
490 | /* initiate DMA transfer */ | ||
491 | if (flctl->chan_fifo0_tx && rlen >= 32 && | ||
492 | flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0) | ||
493 | return; /* DMA success */ | ||
494 | |||
495 | /* do polling transfer */ | ||
327 | for (i = 0; i < len_4align; i++) { | 496 | for (i = 0; i < len_4align; i++) { |
328 | wait_wecfifo_ready(flctl); | 497 | wait_wecfifo_ready(flctl); |
329 | writel(cpu_to_be32(data[i]), FLECFIFO(flctl)); | 498 | writel(buf[i], FLECFIFO(flctl)); |
330 | } | 499 | } |
331 | } | 500 | } |
332 | 501 | ||
@@ -750,41 +919,35 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr) | |||
750 | static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 919 | static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
751 | { | 920 | { |
752 | struct sh_flctl *flctl = mtd_to_flctl(mtd); | 921 | struct sh_flctl *flctl = mtd_to_flctl(mtd); |
753 | int index = flctl->index; | ||
754 | 922 | ||
755 | memcpy(&flctl->done_buff[index], buf, len); | 923 | memcpy(&flctl->done_buff[flctl->index], buf, len); |
756 | flctl->index += len; | 924 | flctl->index += len; |
757 | } | 925 | } |
758 | 926 | ||
759 | static uint8_t flctl_read_byte(struct mtd_info *mtd) | 927 | static uint8_t flctl_read_byte(struct mtd_info *mtd) |
760 | { | 928 | { |
761 | struct sh_flctl *flctl = mtd_to_flctl(mtd); | 929 | struct sh_flctl *flctl = mtd_to_flctl(mtd); |
762 | int index = flctl->index; | ||
763 | uint8_t data; | 930 | uint8_t data; |
764 | 931 | ||
765 | data = flctl->done_buff[index]; | 932 | data = flctl->done_buff[flctl->index]; |
766 | flctl->index++; | 933 | flctl->index++; |
767 | return data; | 934 | return data; |
768 | } | 935 | } |
769 | 936 | ||
770 | static uint16_t flctl_read_word(struct mtd_info *mtd) | 937 | static uint16_t flctl_read_word(struct mtd_info *mtd) |
771 | { | 938 | { |
772 | struct sh_flctl *flctl = mtd_to_flctl(mtd); | 939 | struct sh_flctl *flctl = mtd_to_flctl(mtd); |
773 | int index = flctl->index; | 940 | uint16_t *buf = (uint16_t *)&flctl->done_buff[flctl->index]; |
774 | uint16_t data; | ||
775 | uint16_t *buf = (uint16_t *)&flctl->done_buff[index]; | ||
776 | 941 | ||
777 | data = *buf; | 942 | flctl->index += 2; |
778 | flctl->index += 2; | 943 | return *buf; |
779 | return data; | ||
780 | } | 944 | } |
781 | 945 | ||
782 | static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 946 | static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
783 | { | 947 | { |
784 | struct sh_flctl *flctl = mtd_to_flctl(mtd); | 948 | struct sh_flctl *flctl = mtd_to_flctl(mtd); |
785 | int index = flctl->index; | ||
786 | 949 | ||
787 | memcpy(buf, &flctl->done_buff[index], len); | 950 | memcpy(buf, &flctl->done_buff[flctl->index], len); |
788 | flctl->index += len; | 951 | flctl->index += len; |
789 | } | 952 | } |
790 | 953 | ||
@@ -858,7 +1021,74 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id) | |||
858 | return IRQ_HANDLED; | 1021 | return IRQ_HANDLED; |
859 | } | 1022 | } |
860 | 1023 | ||
861 | static int __devinit flctl_probe(struct platform_device *pdev) | 1024 | #ifdef CONFIG_OF |
1025 | struct flctl_soc_config { | ||
1026 | unsigned long flcmncr_val; | ||
1027 | unsigned has_hwecc:1; | ||
1028 | unsigned use_holden:1; | ||
1029 | }; | ||
1030 | |||
1031 | static struct flctl_soc_config flctl_sh7372_config = { | ||
1032 | .flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL, | ||
1033 | .has_hwecc = 1, | ||
1034 | .use_holden = 1, | ||
1035 | }; | ||
1036 | |||
1037 | static const struct of_device_id of_flctl_match[] = { | ||
1038 | { .compatible = "renesas,shmobile-flctl-sh7372", | ||
1039 | .data = &flctl_sh7372_config }, | ||
1040 | {}, | ||
1041 | }; | ||
1042 | MODULE_DEVICE_TABLE(of, of_flctl_match); | ||
1043 | |||
1044 | static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) | ||
1045 | { | ||
1046 | const struct of_device_id *match; | ||
1047 | struct flctl_soc_config *config; | ||
1048 | struct sh_flctl_platform_data *pdata; | ||
1049 | struct device_node *dn = dev->of_node; | ||
1050 | int ret; | ||
1051 | |||
1052 | match = of_match_device(of_flctl_match, dev); | ||
1053 | if (match) | ||
1054 | config = (struct flctl_soc_config *)match->data; | ||
1055 | else { | ||
1056 | dev_err(dev, "%s: no OF configuration attached\n", __func__); | ||
1057 | return NULL; | ||
1058 | } | ||
1059 | |||
1060 | pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data), | ||
1061 | GFP_KERNEL); | ||
1062 | if (!pdata) { | ||
1063 | dev_err(dev, "%s: failed to allocate config data\n", __func__); | ||
1064 | return NULL; | ||
1065 | } | ||
1066 | |||
1067 | /* set SoC specific options */ | ||
1068 | pdata->flcmncr_val = config->flcmncr_val; | ||
1069 | pdata->has_hwecc = config->has_hwecc; | ||
1070 | pdata->use_holden = config->use_holden; | ||
1071 | |||
1072 | /* parse user defined options */ | ||
1073 | ret = of_get_nand_bus_width(dn); | ||
1074 | if (ret == 16) | ||
1075 | pdata->flcmncr_val |= SEL_16BIT; | ||
1076 | else if (ret != 8) { | ||
1077 | dev_err(dev, "%s: invalid bus width\n", __func__); | ||
1078 | return NULL; | ||
1079 | } | ||
1080 | |||
1081 | return pdata; | ||
1082 | } | ||
1083 | #else /* CONFIG_OF */ | ||
1084 | #define of_flctl_match NULL | ||
1085 | static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) | ||
1086 | { | ||
1087 | return NULL; | ||
1088 | } | ||
1089 | #endif /* CONFIG_OF */ | ||
1090 | |||
1091 | static int flctl_probe(struct platform_device *pdev) | ||
862 | { | 1092 | { |
863 | struct resource *res; | 1093 | struct resource *res; |
864 | struct sh_flctl *flctl; | 1094 | struct sh_flctl *flctl; |
@@ -867,12 +1097,7 @@ static int __devinit flctl_probe(struct platform_device *pdev) | |||
867 | struct sh_flctl_platform_data *pdata; | 1097 | struct sh_flctl_platform_data *pdata; |
868 | int ret = -ENXIO; | 1098 | int ret = -ENXIO; |
869 | int irq; | 1099 | int irq; |
870 | 1100 | struct mtd_part_parser_data ppdata = {}; | |
871 | pdata = pdev->dev.platform_data; | ||
872 | if (pdata == NULL) { | ||
873 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
874 | return -EINVAL; | ||
875 | } | ||
876 | 1101 | ||
877 | flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL); | 1102 | flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL); |
878 | if (!flctl) { | 1103 | if (!flctl) { |
@@ -904,6 +1129,17 @@ static int __devinit flctl_probe(struct platform_device *pdev) | |||
904 | goto err_flste; | 1129 | goto err_flste; |
905 | } | 1130 | } |
906 | 1131 | ||
1132 | if (pdev->dev.of_node) | ||
1133 | pdata = flctl_parse_dt(&pdev->dev); | ||
1134 | else | ||
1135 | pdata = pdev->dev.platform_data; | ||
1136 | |||
1137 | if (!pdata) { | ||
1138 | dev_err(&pdev->dev, "no setup data defined\n"); | ||
1139 | ret = -EINVAL; | ||
1140 | goto err_pdata; | ||
1141 | } | ||
1142 | |||
907 | platform_set_drvdata(pdev, flctl); | 1143 | platform_set_drvdata(pdev, flctl); |
908 | flctl_mtd = &flctl->mtd; | 1144 | flctl_mtd = &flctl->mtd; |
909 | nand = &flctl->chip; | 1145 | nand = &flctl->chip; |
@@ -932,6 +1168,8 @@ static int __devinit flctl_probe(struct platform_device *pdev) | |||
932 | pm_runtime_enable(&pdev->dev); | 1168 | pm_runtime_enable(&pdev->dev); |
933 | pm_runtime_resume(&pdev->dev); | 1169 | pm_runtime_resume(&pdev->dev); |
934 | 1170 | ||
1171 | flctl_setup_dma(flctl); | ||
1172 | |||
935 | ret = nand_scan_ident(flctl_mtd, 1, NULL); | 1173 | ret = nand_scan_ident(flctl_mtd, 1, NULL); |
936 | if (ret) | 1174 | if (ret) |
937 | goto err_chip; | 1175 | goto err_chip; |
@@ -944,12 +1182,16 @@ static int __devinit flctl_probe(struct platform_device *pdev) | |||
944 | if (ret) | 1182 | if (ret) |
945 | goto err_chip; | 1183 | goto err_chip; |
946 | 1184 | ||
947 | mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts); | 1185 | ppdata.of_node = pdev->dev.of_node; |
1186 | ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts, | ||
1187 | pdata->nr_parts); | ||
948 | 1188 | ||
949 | return 0; | 1189 | return 0; |
950 | 1190 | ||
951 | err_chip: | 1191 | err_chip: |
1192 | flctl_release_dma(flctl); | ||
952 | pm_runtime_disable(&pdev->dev); | 1193 | pm_runtime_disable(&pdev->dev); |
1194 | err_pdata: | ||
953 | free_irq(irq, flctl); | 1195 | free_irq(irq, flctl); |
954 | err_flste: | 1196 | err_flste: |
955 | iounmap(flctl->reg); | 1197 | iounmap(flctl->reg); |
@@ -958,10 +1200,11 @@ err_iomap: | |||
958 | return ret; | 1200 | return ret; |
959 | } | 1201 | } |
960 | 1202 | ||
961 | static int __devexit flctl_remove(struct platform_device *pdev) | 1203 | static int flctl_remove(struct platform_device *pdev) |
962 | { | 1204 | { |
963 | struct sh_flctl *flctl = platform_get_drvdata(pdev); | 1205 | struct sh_flctl *flctl = platform_get_drvdata(pdev); |
964 | 1206 | ||
1207 | flctl_release_dma(flctl); | ||
965 | nand_release(&flctl->mtd); | 1208 | nand_release(&flctl->mtd); |
966 | pm_runtime_disable(&pdev->dev); | 1209 | pm_runtime_disable(&pdev->dev); |
967 | free_irq(platform_get_irq(pdev, 0), flctl); | 1210 | free_irq(platform_get_irq(pdev, 0), flctl); |
@@ -976,6 +1219,7 @@ static struct platform_driver flctl_driver = { | |||
976 | .driver = { | 1219 | .driver = { |
977 | .name = "sh_flctl", | 1220 | .name = "sh_flctl", |
978 | .owner = THIS_MODULE, | 1221 | .owner = THIS_MODULE, |
1222 | .of_match_table = of_flctl_match, | ||
979 | }, | 1223 | }, |
980 | }; | 1224 | }; |
981 | 1225 | ||
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 3421e3762a5a..127bc4271821 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -106,7 +106,7 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, | |||
106 | /* | 106 | /* |
107 | * Main initialization routine | 107 | * Main initialization routine |
108 | */ | 108 | */ |
109 | static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | 109 | static int sharpsl_nand_probe(struct platform_device *pdev) |
110 | { | 110 | { |
111 | struct nand_chip *this; | 111 | struct nand_chip *this; |
112 | struct resource *r; | 112 | struct resource *r; |
@@ -205,7 +205,7 @@ err_get_res: | |||
205 | /* | 205 | /* |
206 | * Clean up routine | 206 | * Clean up routine |
207 | */ | 207 | */ |
208 | static int __devexit sharpsl_nand_remove(struct platform_device *pdev) | 208 | static int sharpsl_nand_remove(struct platform_device *pdev) |
209 | { | 209 | { |
210 | struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev); | 210 | struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev); |
211 | 211 | ||
@@ -228,7 +228,7 @@ static struct platform_driver sharpsl_nand_driver = { | |||
228 | .owner = THIS_MODULE, | 228 | .owner = THIS_MODULE, |
229 | }, | 229 | }, |
230 | .probe = sharpsl_nand_probe, | 230 | .probe = sharpsl_nand_probe, |
231 | .remove = __devexit_p(sharpsl_nand_remove), | 231 | .remove = sharpsl_nand_remove, |
232 | }; | 232 | }; |
233 | 233 | ||
234 | module_platform_driver(sharpsl_nand_driver); | 234 | module_platform_driver(sharpsl_nand_driver); |
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index f3f28fafbf7a..09dde7d27178 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c | |||
@@ -140,7 +140,7 @@ static int socrates_nand_device_ready(struct mtd_info *mtd) | |||
140 | /* | 140 | /* |
141 | * Probe for the NAND device. | 141 | * Probe for the NAND device. |
142 | */ | 142 | */ |
143 | static int __devinit socrates_nand_probe(struct platform_device *ofdev) | 143 | static int socrates_nand_probe(struct platform_device *ofdev) |
144 | { | 144 | { |
145 | struct socrates_nand_host *host; | 145 | struct socrates_nand_host *host; |
146 | struct mtd_info *mtd; | 146 | struct mtd_info *mtd; |
@@ -220,7 +220,7 @@ out: | |||
220 | /* | 220 | /* |
221 | * Remove a NAND device. | 221 | * Remove a NAND device. |
222 | */ | 222 | */ |
223 | static int __devexit socrates_nand_remove(struct platform_device *ofdev) | 223 | static int socrates_nand_remove(struct platform_device *ofdev) |
224 | { | 224 | { |
225 | struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); | 225 | struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); |
226 | struct mtd_info *mtd = &host->mtd; | 226 | struct mtd_info *mtd = &host->mtd; |
@@ -251,7 +251,7 @@ static struct platform_driver socrates_nand_driver = { | |||
251 | .of_match_table = socrates_nand_match, | 251 | .of_match_table = socrates_nand_match, |
252 | }, | 252 | }, |
253 | .probe = socrates_nand_probe, | 253 | .probe = socrates_nand_probe, |
254 | .remove = __devexit_p(socrates_nand_remove), | 254 | .remove = socrates_nand_remove, |
255 | }; | 255 | }; |
256 | 256 | ||
257 | module_platform_driver(socrates_nand_driver); | 257 | module_platform_driver(socrates_nand_driver); |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index d9127e2ed808..dbd3aa574eaf 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
@@ -71,7 +71,10 @@ static int parse_ofpart_partitions(struct mtd_info *master, | |||
71 | (*pparts)[i].name = (char *)partname; | 71 | (*pparts)[i].name = (char *)partname; |
72 | 72 | ||
73 | if (of_get_property(pp, "read-only", &len)) | 73 | if (of_get_property(pp, "read-only", &len)) |
74 | (*pparts)[i].mask_flags = MTD_WRITEABLE; | 74 | (*pparts)[i].mask_flags |= MTD_WRITEABLE; |
75 | |||
76 | if (of_get_property(pp, "lock", &len)) | ||
77 | (*pparts)[i].mask_flags |= MTD_POWERUP_LOCK; | ||
75 | 78 | ||
76 | i++; | 79 | i++; |
77 | } | 80 | } |
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 1c4f97c63e62..9f11562f849d 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c | |||
@@ -35,7 +35,7 @@ struct onenand_info { | |||
35 | struct onenand_chip onenand; | 35 | struct onenand_chip onenand; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static int __devinit generic_onenand_probe(struct platform_device *pdev) | 38 | static int generic_onenand_probe(struct platform_device *pdev) |
39 | { | 39 | { |
40 | struct onenand_info *info; | 40 | struct onenand_info *info; |
41 | struct onenand_platform_data *pdata = pdev->dev.platform_data; | 41 | struct onenand_platform_data *pdata = pdev->dev.platform_data; |
@@ -88,7 +88,7 @@ out_free_info: | |||
88 | return err; | 88 | return err; |
89 | } | 89 | } |
90 | 90 | ||
91 | static int __devexit generic_onenand_remove(struct platform_device *pdev) | 91 | static int generic_onenand_remove(struct platform_device *pdev) |
92 | { | 92 | { |
93 | struct onenand_info *info = platform_get_drvdata(pdev); | 93 | struct onenand_info *info = platform_get_drvdata(pdev); |
94 | struct resource *res = pdev->resource; | 94 | struct resource *res = pdev->resource; |
@@ -112,7 +112,7 @@ static struct platform_driver generic_onenand_driver = { | |||
112 | .owner = THIS_MODULE, | 112 | .owner = THIS_MODULE, |
113 | }, | 113 | }, |
114 | .probe = generic_onenand_probe, | 114 | .probe = generic_onenand_probe, |
115 | .remove = __devexit_p(generic_onenand_remove), | 115 | .remove = generic_onenand_remove, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | module_platform_driver(generic_onenand_driver); | 118 | module_platform_driver(generic_onenand_driver); |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 00cd3da29435..065f3fe02a2f 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -630,7 +630,7 @@ static int omap2_onenand_disable(struct mtd_info *mtd) | |||
630 | return ret; | 630 | return ret; |
631 | } | 631 | } |
632 | 632 | ||
633 | static int __devinit omap2_onenand_probe(struct platform_device *pdev) | 633 | static int omap2_onenand_probe(struct platform_device *pdev) |
634 | { | 634 | { |
635 | struct omap_onenand_platform_data *pdata; | 635 | struct omap_onenand_platform_data *pdata; |
636 | struct omap2_onenand *c; | 636 | struct omap2_onenand *c; |
@@ -799,7 +799,7 @@ err_kfree: | |||
799 | return r; | 799 | return r; |
800 | } | 800 | } |
801 | 801 | ||
802 | static int __devexit omap2_onenand_remove(struct platform_device *pdev) | 802 | static int omap2_onenand_remove(struct platform_device *pdev) |
803 | { | 803 | { |
804 | struct omap2_onenand *c = dev_get_drvdata(&pdev->dev); | 804 | struct omap2_onenand *c = dev_get_drvdata(&pdev->dev); |
805 | 805 | ||
@@ -822,7 +822,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) | |||
822 | 822 | ||
823 | static struct platform_driver omap2_onenand_driver = { | 823 | static struct platform_driver omap2_onenand_driver = { |
824 | .probe = omap2_onenand_probe, | 824 | .probe = omap2_onenand_probe, |
825 | .remove = __devexit_p(omap2_onenand_remove), | 825 | .remove = omap2_onenand_remove, |
826 | .shutdown = omap2_onenand_shutdown, | 826 | .shutdown = omap2_onenand_shutdown, |
827 | .driver = { | 827 | .driver = { |
828 | .name = DRIVER_NAME, | 828 | .name = DRIVER_NAME, |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 8e4b3f2742ba..33f2a8fb8df9 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -1053,7 +1053,7 @@ onenand_fail: | |||
1053 | return err; | 1053 | return err; |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | static int __devexit s3c_onenand_remove(struct platform_device *pdev) | 1056 | static int s3c_onenand_remove(struct platform_device *pdev) |
1057 | { | 1057 | { |
1058 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1058 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
1059 | 1059 | ||
@@ -1130,7 +1130,7 @@ static struct platform_driver s3c_onenand_driver = { | |||
1130 | }, | 1130 | }, |
1131 | .id_table = s3c_onenand_driver_ids, | 1131 | .id_table = s3c_onenand_driver_ids, |
1132 | .probe = s3c_onenand_probe, | 1132 | .probe = s3c_onenand_probe, |
1133 | .remove = __devexit_p(s3c_onenand_remove), | 1133 | .remove = s3c_onenand_remove, |
1134 | }; | 1134 | }; |
1135 | 1135 | ||
1136 | module_platform_driver(s3c_onenand_driver); | 1136 | module_platform_driver(s3c_onenand_driver); |
diff --git a/drivers/mtd/tests/mtd_nandbiterrs.c b/drivers/mtd/tests/mtd_nandbiterrs.c index cc8d62cb280c..207bf9a9972f 100644 --- a/drivers/mtd/tests/mtd_nandbiterrs.c +++ b/drivers/mtd/tests/mtd_nandbiterrs.c | |||
@@ -39,6 +39,9 @@ | |||
39 | * this program; see the file COPYING. If not, write to the Free Software | 39 | * this program; see the file COPYING. If not, write to the Free Software |
40 | * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 40 | * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
41 | */ | 41 | */ |
42 | |||
43 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
44 | |||
42 | #include <linux/init.h> | 45 | #include <linux/init.h> |
43 | #include <linux/module.h> | 46 | #include <linux/module.h> |
44 | #include <linux/moduleparam.h> | 47 | #include <linux/moduleparam.h> |
@@ -47,8 +50,6 @@ | |||
47 | #include <linux/mtd/nand.h> | 50 | #include <linux/mtd/nand.h> |
48 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
49 | 52 | ||
50 | #define msg(FMT, VA...) pr_info("mtd_nandbiterrs: "FMT, ##VA) | ||
51 | |||
52 | static int dev; | 53 | static int dev; |
53 | module_param(dev, int, S_IRUGO); | 54 | module_param(dev, int, S_IRUGO); |
54 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 55 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -103,7 +104,7 @@ static int erase_block(void) | |||
103 | struct erase_info ei; | 104 | struct erase_info ei; |
104 | loff_t addr = eraseblock * mtd->erasesize; | 105 | loff_t addr = eraseblock * mtd->erasesize; |
105 | 106 | ||
106 | msg("erase_block\n"); | 107 | pr_info("erase_block\n"); |
107 | 108 | ||
108 | memset(&ei, 0, sizeof(struct erase_info)); | 109 | memset(&ei, 0, sizeof(struct erase_info)); |
109 | ei.mtd = mtd; | 110 | ei.mtd = mtd; |
@@ -112,7 +113,7 @@ static int erase_block(void) | |||
112 | 113 | ||
113 | err = mtd_erase(mtd, &ei); | 114 | err = mtd_erase(mtd, &ei); |
114 | if (err || ei.state == MTD_ERASE_FAILED) { | 115 | if (err || ei.state == MTD_ERASE_FAILED) { |
115 | msg("error %d while erasing\n", err); | 116 | pr_err("error %d while erasing\n", err); |
116 | if (!err) | 117 | if (!err) |
117 | err = -EIO; | 118 | err = -EIO; |
118 | return err; | 119 | return err; |
@@ -128,11 +129,11 @@ static int write_page(int log) | |||
128 | size_t written; | 129 | size_t written; |
129 | 130 | ||
130 | if (log) | 131 | if (log) |
131 | msg("write_page\n"); | 132 | pr_info("write_page\n"); |
132 | 133 | ||
133 | err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer); | 134 | err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer); |
134 | if (err || written != mtd->writesize) { | 135 | if (err || written != mtd->writesize) { |
135 | msg("error: write failed at %#llx\n", (long long)offset); | 136 | pr_err("error: write failed at %#llx\n", (long long)offset); |
136 | if (!err) | 137 | if (!err) |
137 | err = -EIO; | 138 | err = -EIO; |
138 | } | 139 | } |
@@ -147,7 +148,7 @@ static int rewrite_page(int log) | |||
147 | struct mtd_oob_ops ops; | 148 | struct mtd_oob_ops ops; |
148 | 149 | ||
149 | if (log) | 150 | if (log) |
150 | msg("rewrite page\n"); | 151 | pr_info("rewrite page\n"); |
151 | 152 | ||
152 | ops.mode = MTD_OPS_RAW; /* No ECC */ | 153 | ops.mode = MTD_OPS_RAW; /* No ECC */ |
153 | ops.len = mtd->writesize; | 154 | ops.len = mtd->writesize; |
@@ -160,7 +161,7 @@ static int rewrite_page(int log) | |||
160 | 161 | ||
161 | err = mtd_write_oob(mtd, offset, &ops); | 162 | err = mtd_write_oob(mtd, offset, &ops); |
162 | if (err || ops.retlen != mtd->writesize) { | 163 | if (err || ops.retlen != mtd->writesize) { |
163 | msg("error: write_oob failed (%d)\n", err); | 164 | pr_err("error: write_oob failed (%d)\n", err); |
164 | if (!err) | 165 | if (!err) |
165 | err = -EIO; | 166 | err = -EIO; |
166 | } | 167 | } |
@@ -177,7 +178,7 @@ static int read_page(int log) | |||
177 | struct mtd_ecc_stats oldstats; | 178 | struct mtd_ecc_stats oldstats; |
178 | 179 | ||
179 | if (log) | 180 | if (log) |
180 | msg("read_page\n"); | 181 | pr_info("read_page\n"); |
181 | 182 | ||
182 | /* Saving last mtd stats */ | 183 | /* Saving last mtd stats */ |
183 | memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats)); | 184 | memcpy(&oldstats, &mtd->ecc_stats, sizeof(oldstats)); |
@@ -187,7 +188,7 @@ static int read_page(int log) | |||
187 | err = mtd->ecc_stats.corrected - oldstats.corrected; | 188 | err = mtd->ecc_stats.corrected - oldstats.corrected; |
188 | 189 | ||
189 | if (err < 0 || read != mtd->writesize) { | 190 | if (err < 0 || read != mtd->writesize) { |
190 | msg("error: read failed at %#llx\n", (long long)offset); | 191 | pr_err("error: read failed at %#llx\n", (long long)offset); |
191 | if (err >= 0) | 192 | if (err >= 0) |
192 | err = -EIO; | 193 | err = -EIO; |
193 | } | 194 | } |
@@ -201,11 +202,11 @@ static int verify_page(int log) | |||
201 | unsigned i, errs = 0; | 202 | unsigned i, errs = 0; |
202 | 203 | ||
203 | if (log) | 204 | if (log) |
204 | msg("verify_page\n"); | 205 | pr_info("verify_page\n"); |
205 | 206 | ||
206 | for (i = 0; i < mtd->writesize; i++) { | 207 | for (i = 0; i < mtd->writesize; i++) { |
207 | if (rbuffer[i] != hash(i+seed)) { | 208 | if (rbuffer[i] != hash(i+seed)) { |
208 | msg("Error: page offset %u, expected %02x, got %02x\n", | 209 | pr_err("Error: page offset %u, expected %02x, got %02x\n", |
209 | i, hash(i+seed), rbuffer[i]); | 210 | i, hash(i+seed), rbuffer[i]); |
210 | errs++; | 211 | errs++; |
211 | } | 212 | } |
@@ -230,13 +231,13 @@ static int insert_biterror(unsigned byte) | |||
230 | for (bit = 7; bit >= 0; bit--) { | 231 | for (bit = 7; bit >= 0; bit--) { |
231 | if (CBIT(wbuffer[byte], bit)) { | 232 | if (CBIT(wbuffer[byte], bit)) { |
232 | BCLR(wbuffer[byte], bit); | 233 | BCLR(wbuffer[byte], bit); |
233 | msg("Inserted biterror @ %u/%u\n", byte, bit); | 234 | pr_info("Inserted biterror @ %u/%u\n", byte, bit); |
234 | return 0; | 235 | return 0; |
235 | } | 236 | } |
236 | } | 237 | } |
237 | byte++; | 238 | byte++; |
238 | } | 239 | } |
239 | msg("biterror: Failed to find a '1' bit\n"); | 240 | pr_err("biterror: Failed to find a '1' bit\n"); |
240 | return -EIO; | 241 | return -EIO; |
241 | } | 242 | } |
242 | 243 | ||
@@ -248,7 +249,7 @@ static int incremental_errors_test(void) | |||
248 | unsigned i; | 249 | unsigned i; |
249 | unsigned errs_per_subpage = 0; | 250 | unsigned errs_per_subpage = 0; |
250 | 251 | ||
251 | msg("incremental biterrors test\n"); | 252 | pr_info("incremental biterrors test\n"); |
252 | 253 | ||
253 | for (i = 0; i < mtd->writesize; i++) | 254 | for (i = 0; i < mtd->writesize; i++) |
254 | wbuffer[i] = hash(i+seed); | 255 | wbuffer[i] = hash(i+seed); |
@@ -265,9 +266,9 @@ static int incremental_errors_test(void) | |||
265 | 266 | ||
266 | err = read_page(1); | 267 | err = read_page(1); |
267 | if (err > 0) | 268 | if (err > 0) |
268 | msg("Read reported %d corrected bit errors\n", err); | 269 | pr_info("Read reported %d corrected bit errors\n", err); |
269 | if (err < 0) { | 270 | if (err < 0) { |
270 | msg("After %d biterrors per subpage, read reported error %d\n", | 271 | pr_err("After %d biterrors per subpage, read reported error %d\n", |
271 | errs_per_subpage, err); | 272 | errs_per_subpage, err); |
272 | err = 0; | 273 | err = 0; |
273 | goto exit; | 274 | goto exit; |
@@ -275,11 +276,11 @@ static int incremental_errors_test(void) | |||
275 | 276 | ||
276 | err = verify_page(1); | 277 | err = verify_page(1); |
277 | if (err) { | 278 | if (err) { |
278 | msg("ECC failure, read data is incorrect despite read success\n"); | 279 | pr_err("ECC failure, read data is incorrect despite read success\n"); |
279 | goto exit; | 280 | goto exit; |
280 | } | 281 | } |
281 | 282 | ||
282 | msg("Successfully corrected %d bit errors per subpage\n", | 283 | pr_info("Successfully corrected %d bit errors per subpage\n", |
283 | errs_per_subpage); | 284 | errs_per_subpage); |
284 | 285 | ||
285 | for (i = 0; i < subcount; i++) { | 286 | for (i = 0; i < subcount; i++) { |
@@ -311,7 +312,7 @@ static int overwrite_test(void) | |||
311 | 312 | ||
312 | memset(bitstats, 0, sizeof(bitstats)); | 313 | memset(bitstats, 0, sizeof(bitstats)); |
313 | 314 | ||
314 | msg("overwrite biterrors test\n"); | 315 | pr_info("overwrite biterrors test\n"); |
315 | 316 | ||
316 | for (i = 0; i < mtd->writesize; i++) | 317 | for (i = 0; i < mtd->writesize; i++) |
317 | wbuffer[i] = hash(i+seed); | 318 | wbuffer[i] = hash(i+seed); |
@@ -329,18 +330,18 @@ static int overwrite_test(void) | |||
329 | err = read_page(0); | 330 | err = read_page(0); |
330 | if (err >= 0) { | 331 | if (err >= 0) { |
331 | if (err >= MAXBITS) { | 332 | if (err >= MAXBITS) { |
332 | msg("Implausible number of bit errors corrected\n"); | 333 | pr_info("Implausible number of bit errors corrected\n"); |
333 | err = -EIO; | 334 | err = -EIO; |
334 | break; | 335 | break; |
335 | } | 336 | } |
336 | bitstats[err]++; | 337 | bitstats[err]++; |
337 | if (err > max_corrected) { | 338 | if (err > max_corrected) { |
338 | max_corrected = err; | 339 | max_corrected = err; |
339 | msg("Read reported %d corrected bit errors\n", | 340 | pr_info("Read reported %d corrected bit errors\n", |
340 | err); | 341 | err); |
341 | } | 342 | } |
342 | } else { /* err < 0 */ | 343 | } else { /* err < 0 */ |
343 | msg("Read reported error %d\n", err); | 344 | pr_info("Read reported error %d\n", err); |
344 | err = 0; | 345 | err = 0; |
345 | break; | 346 | break; |
346 | } | 347 | } |
@@ -348,7 +349,7 @@ static int overwrite_test(void) | |||
348 | err = verify_page(0); | 349 | err = verify_page(0); |
349 | if (err) { | 350 | if (err) { |
350 | bitstats[max_corrected] = opno; | 351 | bitstats[max_corrected] = opno; |
351 | msg("ECC failure, read data is incorrect despite read success\n"); | 352 | pr_info("ECC failure, read data is incorrect despite read success\n"); |
352 | break; | 353 | break; |
353 | } | 354 | } |
354 | 355 | ||
@@ -357,9 +358,9 @@ static int overwrite_test(void) | |||
357 | 358 | ||
358 | /* At this point bitstats[0] contains the number of ops with no bit | 359 | /* At this point bitstats[0] contains the number of ops with no bit |
359 | * errors, bitstats[1] the number of ops with 1 bit error, etc. */ | 360 | * errors, bitstats[1] the number of ops with 1 bit error, etc. */ |
360 | msg("Bit error histogram (%d operations total):\n", opno); | 361 | pr_info("Bit error histogram (%d operations total):\n", opno); |
361 | for (i = 0; i < max_corrected; i++) | 362 | for (i = 0; i < max_corrected; i++) |
362 | msg("Page reads with %3d corrected bit errors: %d\n", | 363 | pr_info("Page reads with %3d corrected bit errors: %d\n", |
363 | i, bitstats[i]); | 364 | i, bitstats[i]); |
364 | 365 | ||
365 | exit: | 366 | exit: |
@@ -370,36 +371,36 @@ static int __init mtd_nandbiterrs_init(void) | |||
370 | { | 371 | { |
371 | int err = 0; | 372 | int err = 0; |
372 | 373 | ||
373 | msg("\n"); | 374 | printk("\n"); |
374 | msg("==================================================\n"); | 375 | printk(KERN_INFO "==================================================\n"); |
375 | msg("MTD device: %d\n", dev); | 376 | pr_info("MTD device: %d\n", dev); |
376 | 377 | ||
377 | mtd = get_mtd_device(NULL, dev); | 378 | mtd = get_mtd_device(NULL, dev); |
378 | if (IS_ERR(mtd)) { | 379 | if (IS_ERR(mtd)) { |
379 | err = PTR_ERR(mtd); | 380 | err = PTR_ERR(mtd); |
380 | msg("error: cannot get MTD device\n"); | 381 | pr_err("error: cannot get MTD device\n"); |
381 | goto exit_mtddev; | 382 | goto exit_mtddev; |
382 | } | 383 | } |
383 | 384 | ||
384 | if (mtd->type != MTD_NANDFLASH) { | 385 | if (mtd->type != MTD_NANDFLASH) { |
385 | msg("this test requires NAND flash\n"); | 386 | pr_info("this test requires NAND flash\n"); |
386 | err = -ENODEV; | 387 | err = -ENODEV; |
387 | goto exit_nand; | 388 | goto exit_nand; |
388 | } | 389 | } |
389 | 390 | ||
390 | msg("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n", | 391 | pr_info("MTD device size %llu, eraseblock=%u, page=%u, oob=%u\n", |
391 | (unsigned long long)mtd->size, mtd->erasesize, | 392 | (unsigned long long)mtd->size, mtd->erasesize, |
392 | mtd->writesize, mtd->oobsize); | 393 | mtd->writesize, mtd->oobsize); |
393 | 394 | ||
394 | subsize = mtd->writesize >> mtd->subpage_sft; | 395 | subsize = mtd->writesize >> mtd->subpage_sft; |
395 | subcount = mtd->writesize / subsize; | 396 | subcount = mtd->writesize / subsize; |
396 | 397 | ||
397 | msg("Device uses %d subpages of %d bytes\n", subcount, subsize); | 398 | pr_info("Device uses %d subpages of %d bytes\n", subcount, subsize); |
398 | 399 | ||
399 | offset = page_offset * mtd->writesize; | 400 | offset = page_offset * mtd->writesize; |
400 | eraseblock = mtd_div_by_eb(offset, mtd); | 401 | eraseblock = mtd_div_by_eb(offset, mtd); |
401 | 402 | ||
402 | msg("Using page=%u, offset=%llu, eraseblock=%u\n", | 403 | pr_info("Using page=%u, offset=%llu, eraseblock=%u\n", |
403 | page_offset, offset, eraseblock); | 404 | page_offset, offset, eraseblock); |
404 | 405 | ||
405 | wbuffer = kmalloc(mtd->writesize, GFP_KERNEL); | 406 | wbuffer = kmalloc(mtd->writesize, GFP_KERNEL); |
@@ -432,8 +433,8 @@ static int __init mtd_nandbiterrs_init(void) | |||
432 | goto exit_error; | 433 | goto exit_error; |
433 | 434 | ||
434 | err = -EIO; | 435 | err = -EIO; |
435 | msg("finished successfully.\n"); | 436 | pr_info("finished successfully.\n"); |
436 | msg("==================================================\n"); | 437 | printk(KERN_INFO "==================================================\n"); |
437 | 438 | ||
438 | exit_error: | 439 | exit_error: |
439 | kfree(rbuffer); | 440 | kfree(rbuffer); |
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c index b437fa425077..1eee264509a8 100644 --- a/drivers/mtd/tests/mtd_nandecctest.c +++ b/drivers/mtd/tests/mtd_nandecctest.c | |||
@@ -1,3 +1,5 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
2 | |||
1 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
2 | #include <linux/module.h> | 4 | #include <linux/module.h> |
3 | #include <linux/list.h> | 5 | #include <linux/list.h> |
@@ -264,13 +266,13 @@ static int nand_ecc_test_run(const size_t size) | |||
264 | correct_data, size); | 266 | correct_data, size); |
265 | 267 | ||
266 | if (err) { | 268 | if (err) { |
267 | pr_err("mtd_nandecctest: not ok - %s-%zd\n", | 269 | pr_err("not ok - %s-%zd\n", |
268 | nand_ecc_test[i].name, size); | 270 | nand_ecc_test[i].name, size); |
269 | dump_data_ecc(error_data, error_ecc, | 271 | dump_data_ecc(error_data, error_ecc, |
270 | correct_data, correct_ecc, size); | 272 | correct_data, correct_ecc, size); |
271 | break; | 273 | break; |
272 | } | 274 | } |
273 | pr_info("mtd_nandecctest: ok - %s-%zd\n", | 275 | pr_info("ok - %s-%zd\n", |
274 | nand_ecc_test[i].name, size); | 276 | nand_ecc_test[i].name, size); |
275 | } | 277 | } |
276 | error: | 278 | error: |
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c index ed9b62827f1b..e827fa8cd844 100644 --- a/drivers/mtd/tests/mtd_oobtest.c +++ b/drivers/mtd/tests/mtd_oobtest.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> | 19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <asm/div64.h> | 24 | #include <asm/div64.h> |
23 | #include <linux/init.h> | 25 | #include <linux/init.h> |
24 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -28,8 +30,6 @@ | |||
28 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
29 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
30 | 32 | ||
31 | #define PRINT_PREF KERN_INFO "mtd_oobtest: " | ||
32 | |||
33 | static int dev = -EINVAL; | 33 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 34 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 35 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -80,13 +80,12 @@ static int erase_eraseblock(int ebnum) | |||
80 | 80 | ||
81 | err = mtd_erase(mtd, &ei); | 81 | err = mtd_erase(mtd, &ei); |
82 | if (err) { | 82 | if (err) { |
83 | printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); | 83 | pr_err("error %d while erasing EB %d\n", err, ebnum); |
84 | return err; | 84 | return err; |
85 | } | 85 | } |
86 | 86 | ||
87 | if (ei.state == MTD_ERASE_FAILED) { | 87 | if (ei.state == MTD_ERASE_FAILED) { |
88 | printk(PRINT_PREF "some erase error occurred at EB %d\n", | 88 | pr_err("some erase error occurred at EB %d\n", ebnum); |
89 | ebnum); | ||
90 | return -EIO; | 89 | return -EIO; |
91 | } | 90 | } |
92 | 91 | ||
@@ -98,7 +97,7 @@ static int erase_whole_device(void) | |||
98 | int err; | 97 | int err; |
99 | unsigned int i; | 98 | unsigned int i; |
100 | 99 | ||
101 | printk(PRINT_PREF "erasing whole device\n"); | 100 | pr_info("erasing whole device\n"); |
102 | for (i = 0; i < ebcnt; ++i) { | 101 | for (i = 0; i < ebcnt; ++i) { |
103 | if (bbt[i]) | 102 | if (bbt[i]) |
104 | continue; | 103 | continue; |
@@ -107,7 +106,7 @@ static int erase_whole_device(void) | |||
107 | return err; | 106 | return err; |
108 | cond_resched(); | 107 | cond_resched(); |
109 | } | 108 | } |
110 | printk(PRINT_PREF "erased %u eraseblocks\n", i); | 109 | pr_info("erased %u eraseblocks\n", i); |
111 | return 0; | 110 | return 0; |
112 | } | 111 | } |
113 | 112 | ||
@@ -141,9 +140,9 @@ static int write_eraseblock(int ebnum) | |||
141 | ops.oobbuf = writebuf; | 140 | ops.oobbuf = writebuf; |
142 | err = mtd_write_oob(mtd, addr, &ops); | 141 | err = mtd_write_oob(mtd, addr, &ops); |
143 | if (err || ops.oobretlen != use_len) { | 142 | if (err || ops.oobretlen != use_len) { |
144 | printk(PRINT_PREF "error: writeoob failed at %#llx\n", | 143 | pr_err("error: writeoob failed at %#llx\n", |
145 | (long long)addr); | 144 | (long long)addr); |
146 | printk(PRINT_PREF "error: use_len %d, use_offset %d\n", | 145 | pr_err("error: use_len %d, use_offset %d\n", |
147 | use_len, use_offset); | 146 | use_len, use_offset); |
148 | errcnt += 1; | 147 | errcnt += 1; |
149 | return err ? err : -1; | 148 | return err ? err : -1; |
@@ -160,7 +159,7 @@ static int write_whole_device(void) | |||
160 | int err; | 159 | int err; |
161 | unsigned int i; | 160 | unsigned int i; |
162 | 161 | ||
163 | printk(PRINT_PREF "writing OOBs of whole device\n"); | 162 | pr_info("writing OOBs of whole device\n"); |
164 | for (i = 0; i < ebcnt; ++i) { | 163 | for (i = 0; i < ebcnt; ++i) { |
165 | if (bbt[i]) | 164 | if (bbt[i]) |
166 | continue; | 165 | continue; |
@@ -168,10 +167,10 @@ static int write_whole_device(void) | |||
168 | if (err) | 167 | if (err) |
169 | return err; | 168 | return err; |
170 | if (i % 256 == 0) | 169 | if (i % 256 == 0) |
171 | printk(PRINT_PREF "written up to eraseblock %u\n", i); | 170 | pr_info("written up to eraseblock %u\n", i); |
172 | cond_resched(); | 171 | cond_resched(); |
173 | } | 172 | } |
174 | printk(PRINT_PREF "written %u eraseblocks\n", i); | 173 | pr_info("written %u eraseblocks\n", i); |
175 | return 0; | 174 | return 0; |
176 | } | 175 | } |
177 | 176 | ||
@@ -194,17 +193,17 @@ static int verify_eraseblock(int ebnum) | |||
194 | ops.oobbuf = readbuf; | 193 | ops.oobbuf = readbuf; |
195 | err = mtd_read_oob(mtd, addr, &ops); | 194 | err = mtd_read_oob(mtd, addr, &ops); |
196 | if (err || ops.oobretlen != use_len) { | 195 | if (err || ops.oobretlen != use_len) { |
197 | printk(PRINT_PREF "error: readoob failed at %#llx\n", | 196 | pr_err("error: readoob failed at %#llx\n", |
198 | (long long)addr); | 197 | (long long)addr); |
199 | errcnt += 1; | 198 | errcnt += 1; |
200 | return err ? err : -1; | 199 | return err ? err : -1; |
201 | } | 200 | } |
202 | if (memcmp(readbuf, writebuf, use_len)) { | 201 | if (memcmp(readbuf, writebuf, use_len)) { |
203 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 202 | pr_err("error: verify failed at %#llx\n", |
204 | (long long)addr); | 203 | (long long)addr); |
205 | errcnt += 1; | 204 | errcnt += 1; |
206 | if (errcnt > 1000) { | 205 | if (errcnt > 1000) { |
207 | printk(PRINT_PREF "error: too many errors\n"); | 206 | pr_err("error: too many errors\n"); |
208 | return -1; | 207 | return -1; |
209 | } | 208 | } |
210 | } | 209 | } |
@@ -221,29 +220,28 @@ static int verify_eraseblock(int ebnum) | |||
221 | ops.oobbuf = readbuf; | 220 | ops.oobbuf = readbuf; |
222 | err = mtd_read_oob(mtd, addr, &ops); | 221 | err = mtd_read_oob(mtd, addr, &ops); |
223 | if (err || ops.oobretlen != mtd->ecclayout->oobavail) { | 222 | if (err || ops.oobretlen != mtd->ecclayout->oobavail) { |
224 | printk(PRINT_PREF "error: readoob failed at " | 223 | pr_err("error: readoob failed at %#llx\n", |
225 | "%#llx\n", (long long)addr); | 224 | (long long)addr); |
226 | errcnt += 1; | 225 | errcnt += 1; |
227 | return err ? err : -1; | 226 | return err ? err : -1; |
228 | } | 227 | } |
229 | if (memcmp(readbuf + use_offset, writebuf, use_len)) { | 228 | if (memcmp(readbuf + use_offset, writebuf, use_len)) { |
230 | printk(PRINT_PREF "error: verify failed at " | 229 | pr_err("error: verify failed at %#llx\n", |
231 | "%#llx\n", (long long)addr); | 230 | (long long)addr); |
232 | errcnt += 1; | 231 | errcnt += 1; |
233 | if (errcnt > 1000) { | 232 | if (errcnt > 1000) { |
234 | printk(PRINT_PREF "error: too many " | 233 | pr_err("error: too many errors\n"); |
235 | "errors\n"); | ||
236 | return -1; | 234 | return -1; |
237 | } | 235 | } |
238 | } | 236 | } |
239 | for (k = 0; k < use_offset; ++k) | 237 | for (k = 0; k < use_offset; ++k) |
240 | if (readbuf[k] != 0xff) { | 238 | if (readbuf[k] != 0xff) { |
241 | printk(PRINT_PREF "error: verify 0xff " | 239 | pr_err("error: verify 0xff " |
242 | "failed at %#llx\n", | 240 | "failed at %#llx\n", |
243 | (long long)addr); | 241 | (long long)addr); |
244 | errcnt += 1; | 242 | errcnt += 1; |
245 | if (errcnt > 1000) { | 243 | if (errcnt > 1000) { |
246 | printk(PRINT_PREF "error: too " | 244 | pr_err("error: too " |
247 | "many errors\n"); | 245 | "many errors\n"); |
248 | return -1; | 246 | return -1; |
249 | } | 247 | } |
@@ -251,12 +249,12 @@ static int verify_eraseblock(int ebnum) | |||
251 | for (k = use_offset + use_len; | 249 | for (k = use_offset + use_len; |
252 | k < mtd->ecclayout->oobavail; ++k) | 250 | k < mtd->ecclayout->oobavail; ++k) |
253 | if (readbuf[k] != 0xff) { | 251 | if (readbuf[k] != 0xff) { |
254 | printk(PRINT_PREF "error: verify 0xff " | 252 | pr_err("error: verify 0xff " |
255 | "failed at %#llx\n", | 253 | "failed at %#llx\n", |
256 | (long long)addr); | 254 | (long long)addr); |
257 | errcnt += 1; | 255 | errcnt += 1; |
258 | if (errcnt > 1000) { | 256 | if (errcnt > 1000) { |
259 | printk(PRINT_PREF "error: too " | 257 | pr_err("error: too " |
260 | "many errors\n"); | 258 | "many errors\n"); |
261 | return -1; | 259 | return -1; |
262 | } | 260 | } |
@@ -286,17 +284,17 @@ static int verify_eraseblock_in_one_go(int ebnum) | |||
286 | ops.oobbuf = readbuf; | 284 | ops.oobbuf = readbuf; |
287 | err = mtd_read_oob(mtd, addr, &ops); | 285 | err = mtd_read_oob(mtd, addr, &ops); |
288 | if (err || ops.oobretlen != len) { | 286 | if (err || ops.oobretlen != len) { |
289 | printk(PRINT_PREF "error: readoob failed at %#llx\n", | 287 | pr_err("error: readoob failed at %#llx\n", |
290 | (long long)addr); | 288 | (long long)addr); |
291 | errcnt += 1; | 289 | errcnt += 1; |
292 | return err ? err : -1; | 290 | return err ? err : -1; |
293 | } | 291 | } |
294 | if (memcmp(readbuf, writebuf, len)) { | 292 | if (memcmp(readbuf, writebuf, len)) { |
295 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 293 | pr_err("error: verify failed at %#llx\n", |
296 | (long long)addr); | 294 | (long long)addr); |
297 | errcnt += 1; | 295 | errcnt += 1; |
298 | if (errcnt > 1000) { | 296 | if (errcnt > 1000) { |
299 | printk(PRINT_PREF "error: too many errors\n"); | 297 | pr_err("error: too many errors\n"); |
300 | return -1; | 298 | return -1; |
301 | } | 299 | } |
302 | } | 300 | } |
@@ -309,7 +307,7 @@ static int verify_all_eraseblocks(void) | |||
309 | int err; | 307 | int err; |
310 | unsigned int i; | 308 | unsigned int i; |
311 | 309 | ||
312 | printk(PRINT_PREF "verifying all eraseblocks\n"); | 310 | pr_info("verifying all eraseblocks\n"); |
313 | for (i = 0; i < ebcnt; ++i) { | 311 | for (i = 0; i < ebcnt; ++i) { |
314 | if (bbt[i]) | 312 | if (bbt[i]) |
315 | continue; | 313 | continue; |
@@ -317,10 +315,10 @@ static int verify_all_eraseblocks(void) | |||
317 | if (err) | 315 | if (err) |
318 | return err; | 316 | return err; |
319 | if (i % 256 == 0) | 317 | if (i % 256 == 0) |
320 | printk(PRINT_PREF "verified up to eraseblock %u\n", i); | 318 | pr_info("verified up to eraseblock %u\n", i); |
321 | cond_resched(); | 319 | cond_resched(); |
322 | } | 320 | } |
323 | printk(PRINT_PREF "verified %u eraseblocks\n", i); | 321 | pr_info("verified %u eraseblocks\n", i); |
324 | return 0; | 322 | return 0; |
325 | } | 323 | } |
326 | 324 | ||
@@ -331,7 +329,7 @@ static int is_block_bad(int ebnum) | |||
331 | 329 | ||
332 | ret = mtd_block_isbad(mtd, addr); | 330 | ret = mtd_block_isbad(mtd, addr); |
333 | if (ret) | 331 | if (ret) |
334 | printk(PRINT_PREF "block %d is bad\n", ebnum); | 332 | pr_info("block %d is bad\n", ebnum); |
335 | return ret; | 333 | return ret; |
336 | } | 334 | } |
337 | 335 | ||
@@ -341,18 +339,18 @@ static int scan_for_bad_eraseblocks(void) | |||
341 | 339 | ||
342 | bbt = kmalloc(ebcnt, GFP_KERNEL); | 340 | bbt = kmalloc(ebcnt, GFP_KERNEL); |
343 | if (!bbt) { | 341 | if (!bbt) { |
344 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 342 | pr_err("error: cannot allocate memory\n"); |
345 | return -ENOMEM; | 343 | return -ENOMEM; |
346 | } | 344 | } |
347 | 345 | ||
348 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 346 | pr_info("scanning for bad eraseblocks\n"); |
349 | for (i = 0; i < ebcnt; ++i) { | 347 | for (i = 0; i < ebcnt; ++i) { |
350 | bbt[i] = is_block_bad(i) ? 1 : 0; | 348 | bbt[i] = is_block_bad(i) ? 1 : 0; |
351 | if (bbt[i]) | 349 | if (bbt[i]) |
352 | bad += 1; | 350 | bad += 1; |
353 | cond_resched(); | 351 | cond_resched(); |
354 | } | 352 | } |
355 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); | 353 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); |
356 | return 0; | 354 | return 0; |
357 | } | 355 | } |
358 | 356 | ||
@@ -368,22 +366,22 @@ static int __init mtd_oobtest_init(void) | |||
368 | printk(KERN_INFO "=================================================\n"); | 366 | printk(KERN_INFO "=================================================\n"); |
369 | 367 | ||
370 | if (dev < 0) { | 368 | if (dev < 0) { |
371 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | 369 | pr_info("Please specify a valid mtd-device via module parameter\n"); |
372 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | 370 | pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); |
373 | return -EINVAL; | 371 | return -EINVAL; |
374 | } | 372 | } |
375 | 373 | ||
376 | printk(PRINT_PREF "MTD device: %d\n", dev); | 374 | pr_info("MTD device: %d\n", dev); |
377 | 375 | ||
378 | mtd = get_mtd_device(NULL, dev); | 376 | mtd = get_mtd_device(NULL, dev); |
379 | if (IS_ERR(mtd)) { | 377 | if (IS_ERR(mtd)) { |
380 | err = PTR_ERR(mtd); | 378 | err = PTR_ERR(mtd); |
381 | printk(PRINT_PREF "error: cannot get MTD device\n"); | 379 | pr_err("error: cannot get MTD device\n"); |
382 | return err; | 380 | return err; |
383 | } | 381 | } |
384 | 382 | ||
385 | if (mtd->type != MTD_NANDFLASH) { | 383 | if (mtd->type != MTD_NANDFLASH) { |
386 | printk(PRINT_PREF "this test requires NAND flash\n"); | 384 | pr_info("this test requires NAND flash\n"); |
387 | goto out; | 385 | goto out; |
388 | } | 386 | } |
389 | 387 | ||
@@ -392,7 +390,7 @@ static int __init mtd_oobtest_init(void) | |||
392 | ebcnt = tmp; | 390 | ebcnt = tmp; |
393 | pgcnt = mtd->erasesize / mtd->writesize; | 391 | pgcnt = mtd->erasesize / mtd->writesize; |
394 | 392 | ||
395 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 393 | pr_info("MTD device size %llu, eraseblock size %u, " |
396 | "page size %u, count of eraseblocks %u, pages per " | 394 | "page size %u, count of eraseblocks %u, pages per " |
397 | "eraseblock %u, OOB size %u\n", | 395 | "eraseblock %u, OOB size %u\n", |
398 | (unsigned long long)mtd->size, mtd->erasesize, | 396 | (unsigned long long)mtd->size, mtd->erasesize, |
@@ -401,12 +399,12 @@ static int __init mtd_oobtest_init(void) | |||
401 | err = -ENOMEM; | 399 | err = -ENOMEM; |
402 | readbuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 400 | readbuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
403 | if (!readbuf) { | 401 | if (!readbuf) { |
404 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 402 | pr_err("error: cannot allocate memory\n"); |
405 | goto out; | 403 | goto out; |
406 | } | 404 | } |
407 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 405 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
408 | if (!writebuf) { | 406 | if (!writebuf) { |
409 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 407 | pr_err("error: cannot allocate memory\n"); |
410 | goto out; | 408 | goto out; |
411 | } | 409 | } |
412 | 410 | ||
@@ -420,7 +418,7 @@ static int __init mtd_oobtest_init(void) | |||
420 | vary_offset = 0; | 418 | vary_offset = 0; |
421 | 419 | ||
422 | /* First test: write all OOB, read it back and verify */ | 420 | /* First test: write all OOB, read it back and verify */ |
423 | printk(PRINT_PREF "test 1 of 5\n"); | 421 | pr_info("test 1 of 5\n"); |
424 | 422 | ||
425 | err = erase_whole_device(); | 423 | err = erase_whole_device(); |
426 | if (err) | 424 | if (err) |
@@ -440,7 +438,7 @@ static int __init mtd_oobtest_init(void) | |||
440 | * Second test: write all OOB, a block at a time, read it back and | 438 | * Second test: write all OOB, a block at a time, read it back and |
441 | * verify. | 439 | * verify. |
442 | */ | 440 | */ |
443 | printk(PRINT_PREF "test 2 of 5\n"); | 441 | pr_info("test 2 of 5\n"); |
444 | 442 | ||
445 | err = erase_whole_device(); | 443 | err = erase_whole_device(); |
446 | if (err) | 444 | if (err) |
@@ -453,7 +451,7 @@ static int __init mtd_oobtest_init(void) | |||
453 | 451 | ||
454 | /* Check all eraseblocks */ | 452 | /* Check all eraseblocks */ |
455 | simple_srand(3); | 453 | simple_srand(3); |
456 | printk(PRINT_PREF "verifying all eraseblocks\n"); | 454 | pr_info("verifying all eraseblocks\n"); |
457 | for (i = 0; i < ebcnt; ++i) { | 455 | for (i = 0; i < ebcnt; ++i) { |
458 | if (bbt[i]) | 456 | if (bbt[i]) |
459 | continue; | 457 | continue; |
@@ -461,16 +459,16 @@ static int __init mtd_oobtest_init(void) | |||
461 | if (err) | 459 | if (err) |
462 | goto out; | 460 | goto out; |
463 | if (i % 256 == 0) | 461 | if (i % 256 == 0) |
464 | printk(PRINT_PREF "verified up to eraseblock %u\n", i); | 462 | pr_info("verified up to eraseblock %u\n", i); |
465 | cond_resched(); | 463 | cond_resched(); |
466 | } | 464 | } |
467 | printk(PRINT_PREF "verified %u eraseblocks\n", i); | 465 | pr_info("verified %u eraseblocks\n", i); |
468 | 466 | ||
469 | /* | 467 | /* |
470 | * Third test: write OOB at varying offsets and lengths, read it back | 468 | * Third test: write OOB at varying offsets and lengths, read it back |
471 | * and verify. | 469 | * and verify. |
472 | */ | 470 | */ |
473 | printk(PRINT_PREF "test 3 of 5\n"); | 471 | pr_info("test 3 of 5\n"); |
474 | 472 | ||
475 | err = erase_whole_device(); | 473 | err = erase_whole_device(); |
476 | if (err) | 474 | if (err) |
@@ -503,7 +501,7 @@ static int __init mtd_oobtest_init(void) | |||
503 | vary_offset = 0; | 501 | vary_offset = 0; |
504 | 502 | ||
505 | /* Fourth test: try to write off end of device */ | 503 | /* Fourth test: try to write off end of device */ |
506 | printk(PRINT_PREF "test 4 of 5\n"); | 504 | pr_info("test 4 of 5\n"); |
507 | 505 | ||
508 | err = erase_whole_device(); | 506 | err = erase_whole_device(); |
509 | if (err) | 507 | if (err) |
@@ -522,14 +520,14 @@ static int __init mtd_oobtest_init(void) | |||
522 | ops.ooboffs = mtd->ecclayout->oobavail; | 520 | ops.ooboffs = mtd->ecclayout->oobavail; |
523 | ops.datbuf = NULL; | 521 | ops.datbuf = NULL; |
524 | ops.oobbuf = writebuf; | 522 | ops.oobbuf = writebuf; |
525 | printk(PRINT_PREF "attempting to start write past end of OOB\n"); | 523 | pr_info("attempting to start write past end of OOB\n"); |
526 | printk(PRINT_PREF "an error is expected...\n"); | 524 | pr_info("an error is expected...\n"); |
527 | err = mtd_write_oob(mtd, addr0, &ops); | 525 | err = mtd_write_oob(mtd, addr0, &ops); |
528 | if (err) { | 526 | if (err) { |
529 | printk(PRINT_PREF "error occurred as expected\n"); | 527 | pr_info("error occurred as expected\n"); |
530 | err = 0; | 528 | err = 0; |
531 | } else { | 529 | } else { |
532 | printk(PRINT_PREF "error: can write past end of OOB\n"); | 530 | pr_err("error: can write past end of OOB\n"); |
533 | errcnt += 1; | 531 | errcnt += 1; |
534 | } | 532 | } |
535 | 533 | ||
@@ -542,19 +540,19 @@ static int __init mtd_oobtest_init(void) | |||
542 | ops.ooboffs = mtd->ecclayout->oobavail; | 540 | ops.ooboffs = mtd->ecclayout->oobavail; |
543 | ops.datbuf = NULL; | 541 | ops.datbuf = NULL; |
544 | ops.oobbuf = readbuf; | 542 | ops.oobbuf = readbuf; |
545 | printk(PRINT_PREF "attempting to start read past end of OOB\n"); | 543 | pr_info("attempting to start read past end of OOB\n"); |
546 | printk(PRINT_PREF "an error is expected...\n"); | 544 | pr_info("an error is expected...\n"); |
547 | err = mtd_read_oob(mtd, addr0, &ops); | 545 | err = mtd_read_oob(mtd, addr0, &ops); |
548 | if (err) { | 546 | if (err) { |
549 | printk(PRINT_PREF "error occurred as expected\n"); | 547 | pr_info("error occurred as expected\n"); |
550 | err = 0; | 548 | err = 0; |
551 | } else { | 549 | } else { |
552 | printk(PRINT_PREF "error: can read past end of OOB\n"); | 550 | pr_err("error: can read past end of OOB\n"); |
553 | errcnt += 1; | 551 | errcnt += 1; |
554 | } | 552 | } |
555 | 553 | ||
556 | if (bbt[ebcnt - 1]) | 554 | if (bbt[ebcnt - 1]) |
557 | printk(PRINT_PREF "skipping end of device tests because last " | 555 | pr_info("skipping end of device tests because last " |
558 | "block is bad\n"); | 556 | "block is bad\n"); |
559 | else { | 557 | else { |
560 | /* Attempt to write off end of device */ | 558 | /* Attempt to write off end of device */ |
@@ -566,14 +564,14 @@ static int __init mtd_oobtest_init(void) | |||
566 | ops.ooboffs = 0; | 564 | ops.ooboffs = 0; |
567 | ops.datbuf = NULL; | 565 | ops.datbuf = NULL; |
568 | ops.oobbuf = writebuf; | 566 | ops.oobbuf = writebuf; |
569 | printk(PRINT_PREF "attempting to write past end of device\n"); | 567 | pr_info("attempting to write past end of device\n"); |
570 | printk(PRINT_PREF "an error is expected...\n"); | 568 | pr_info("an error is expected...\n"); |
571 | err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); | 569 | err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); |
572 | if (err) { | 570 | if (err) { |
573 | printk(PRINT_PREF "error occurred as expected\n"); | 571 | pr_info("error occurred as expected\n"); |
574 | err = 0; | 572 | err = 0; |
575 | } else { | 573 | } else { |
576 | printk(PRINT_PREF "error: wrote past end of device\n"); | 574 | pr_err("error: wrote past end of device\n"); |
577 | errcnt += 1; | 575 | errcnt += 1; |
578 | } | 576 | } |
579 | 577 | ||
@@ -586,14 +584,14 @@ static int __init mtd_oobtest_init(void) | |||
586 | ops.ooboffs = 0; | 584 | ops.ooboffs = 0; |
587 | ops.datbuf = NULL; | 585 | ops.datbuf = NULL; |
588 | ops.oobbuf = readbuf; | 586 | ops.oobbuf = readbuf; |
589 | printk(PRINT_PREF "attempting to read past end of device\n"); | 587 | pr_info("attempting to read past end of device\n"); |
590 | printk(PRINT_PREF "an error is expected...\n"); | 588 | pr_info("an error is expected...\n"); |
591 | err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops); | 589 | err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops); |
592 | if (err) { | 590 | if (err) { |
593 | printk(PRINT_PREF "error occurred as expected\n"); | 591 | pr_info("error occurred as expected\n"); |
594 | err = 0; | 592 | err = 0; |
595 | } else { | 593 | } else { |
596 | printk(PRINT_PREF "error: read past end of device\n"); | 594 | pr_err("error: read past end of device\n"); |
597 | errcnt += 1; | 595 | errcnt += 1; |
598 | } | 596 | } |
599 | 597 | ||
@@ -610,14 +608,14 @@ static int __init mtd_oobtest_init(void) | |||
610 | ops.ooboffs = 1; | 608 | ops.ooboffs = 1; |
611 | ops.datbuf = NULL; | 609 | ops.datbuf = NULL; |
612 | ops.oobbuf = writebuf; | 610 | ops.oobbuf = writebuf; |
613 | printk(PRINT_PREF "attempting to write past end of device\n"); | 611 | pr_info("attempting to write past end of device\n"); |
614 | printk(PRINT_PREF "an error is expected...\n"); | 612 | pr_info("an error is expected...\n"); |
615 | err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); | 613 | err = mtd_write_oob(mtd, mtd->size - mtd->writesize, &ops); |
616 | if (err) { | 614 | if (err) { |
617 | printk(PRINT_PREF "error occurred as expected\n"); | 615 | pr_info("error occurred as expected\n"); |
618 | err = 0; | 616 | err = 0; |
619 | } else { | 617 | } else { |
620 | printk(PRINT_PREF "error: wrote past end of device\n"); | 618 | pr_err("error: wrote past end of device\n"); |
621 | errcnt += 1; | 619 | errcnt += 1; |
622 | } | 620 | } |
623 | 621 | ||
@@ -630,20 +628,20 @@ static int __init mtd_oobtest_init(void) | |||
630 | ops.ooboffs = 1; | 628 | ops.ooboffs = 1; |
631 | ops.datbuf = NULL; | 629 | ops.datbuf = NULL; |
632 | ops.oobbuf = readbuf; | 630 | ops.oobbuf = readbuf; |
633 | printk(PRINT_PREF "attempting to read past end of device\n"); | 631 | pr_info("attempting to read past end of device\n"); |
634 | printk(PRINT_PREF "an error is expected...\n"); | 632 | pr_info("an error is expected...\n"); |
635 | err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops); | 633 | err = mtd_read_oob(mtd, mtd->size - mtd->writesize, &ops); |
636 | if (err) { | 634 | if (err) { |
637 | printk(PRINT_PREF "error occurred as expected\n"); | 635 | pr_info("error occurred as expected\n"); |
638 | err = 0; | 636 | err = 0; |
639 | } else { | 637 | } else { |
640 | printk(PRINT_PREF "error: read past end of device\n"); | 638 | pr_err("error: read past end of device\n"); |
641 | errcnt += 1; | 639 | errcnt += 1; |
642 | } | 640 | } |
643 | } | 641 | } |
644 | 642 | ||
645 | /* Fifth test: write / read across block boundaries */ | 643 | /* Fifth test: write / read across block boundaries */ |
646 | printk(PRINT_PREF "test 5 of 5\n"); | 644 | pr_info("test 5 of 5\n"); |
647 | 645 | ||
648 | /* Erase all eraseblocks */ | 646 | /* Erase all eraseblocks */ |
649 | err = erase_whole_device(); | 647 | err = erase_whole_device(); |
@@ -652,7 +650,7 @@ static int __init mtd_oobtest_init(void) | |||
652 | 650 | ||
653 | /* Write all eraseblocks */ | 651 | /* Write all eraseblocks */ |
654 | simple_srand(11); | 652 | simple_srand(11); |
655 | printk(PRINT_PREF "writing OOBs of whole device\n"); | 653 | pr_info("writing OOBs of whole device\n"); |
656 | for (i = 0; i < ebcnt - 1; ++i) { | 654 | for (i = 0; i < ebcnt - 1; ++i) { |
657 | int cnt = 2; | 655 | int cnt = 2; |
658 | int pg; | 656 | int pg; |
@@ -674,17 +672,16 @@ static int __init mtd_oobtest_init(void) | |||
674 | if (err) | 672 | if (err) |
675 | goto out; | 673 | goto out; |
676 | if (i % 256 == 0) | 674 | if (i % 256 == 0) |
677 | printk(PRINT_PREF "written up to eraseblock " | 675 | pr_info("written up to eraseblock %u\n", i); |
678 | "%u\n", i); | ||
679 | cond_resched(); | 676 | cond_resched(); |
680 | addr += mtd->writesize; | 677 | addr += mtd->writesize; |
681 | } | 678 | } |
682 | } | 679 | } |
683 | printk(PRINT_PREF "written %u eraseblocks\n", i); | 680 | pr_info("written %u eraseblocks\n", i); |
684 | 681 | ||
685 | /* Check all eraseblocks */ | 682 | /* Check all eraseblocks */ |
686 | simple_srand(11); | 683 | simple_srand(11); |
687 | printk(PRINT_PREF "verifying all eraseblocks\n"); | 684 | pr_info("verifying all eraseblocks\n"); |
688 | for (i = 0; i < ebcnt - 1; ++i) { | 685 | for (i = 0; i < ebcnt - 1; ++i) { |
689 | if (bbt[i] || bbt[i + 1]) | 686 | if (bbt[i] || bbt[i + 1]) |
690 | continue; | 687 | continue; |
@@ -702,28 +699,28 @@ static int __init mtd_oobtest_init(void) | |||
702 | if (err) | 699 | if (err) |
703 | goto out; | 700 | goto out; |
704 | if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) { | 701 | if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) { |
705 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 702 | pr_err("error: verify failed at %#llx\n", |
706 | (long long)addr); | 703 | (long long)addr); |
707 | errcnt += 1; | 704 | errcnt += 1; |
708 | if (errcnt > 1000) { | 705 | if (errcnt > 1000) { |
709 | printk(PRINT_PREF "error: too many errors\n"); | 706 | pr_err("error: too many errors\n"); |
710 | goto out; | 707 | goto out; |
711 | } | 708 | } |
712 | } | 709 | } |
713 | if (i % 256 == 0) | 710 | if (i % 256 == 0) |
714 | printk(PRINT_PREF "verified up to eraseblock %u\n", i); | 711 | pr_info("verified up to eraseblock %u\n", i); |
715 | cond_resched(); | 712 | cond_resched(); |
716 | } | 713 | } |
717 | printk(PRINT_PREF "verified %u eraseblocks\n", i); | 714 | pr_info("verified %u eraseblocks\n", i); |
718 | 715 | ||
719 | printk(PRINT_PREF "finished with %d errors\n", errcnt); | 716 | pr_info("finished with %d errors\n", errcnt); |
720 | out: | 717 | out: |
721 | kfree(bbt); | 718 | kfree(bbt); |
722 | kfree(writebuf); | 719 | kfree(writebuf); |
723 | kfree(readbuf); | 720 | kfree(readbuf); |
724 | put_mtd_device(mtd); | 721 | put_mtd_device(mtd); |
725 | if (err) | 722 | if (err) |
726 | printk(PRINT_PREF "error %d occurred\n", err); | 723 | pr_info("error %d occurred\n", err); |
727 | printk(KERN_INFO "=================================================\n"); | 724 | printk(KERN_INFO "=================================================\n"); |
728 | return err; | 725 | return err; |
729 | } | 726 | } |
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c index 252ddb092fb2..f93a76f88113 100644 --- a/drivers/mtd/tests/mtd_pagetest.c +++ b/drivers/mtd/tests/mtd_pagetest.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> | 19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <asm/div64.h> | 24 | #include <asm/div64.h> |
23 | #include <linux/init.h> | 25 | #include <linux/init.h> |
24 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -28,8 +30,6 @@ | |||
28 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
29 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
30 | 32 | ||
31 | #define PRINT_PREF KERN_INFO "mtd_pagetest: " | ||
32 | |||
33 | static int dev = -EINVAL; | 33 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 34 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 35 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -79,12 +79,12 @@ static int erase_eraseblock(int ebnum) | |||
79 | 79 | ||
80 | err = mtd_erase(mtd, &ei); | 80 | err = mtd_erase(mtd, &ei); |
81 | if (err) { | 81 | if (err) { |
82 | printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); | 82 | pr_err("error %d while erasing EB %d\n", err, ebnum); |
83 | return err; | 83 | return err; |
84 | } | 84 | } |
85 | 85 | ||
86 | if (ei.state == MTD_ERASE_FAILED) { | 86 | if (ei.state == MTD_ERASE_FAILED) { |
87 | printk(PRINT_PREF "some erase error occurred at EB %d\n", | 87 | pr_err("some erase error occurred at EB %d\n", |
88 | ebnum); | 88 | ebnum); |
89 | return -EIO; | 89 | return -EIO; |
90 | } | 90 | } |
@@ -102,7 +102,7 @@ static int write_eraseblock(int ebnum) | |||
102 | cond_resched(); | 102 | cond_resched(); |
103 | err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf); | 103 | err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf); |
104 | if (err || written != mtd->erasesize) | 104 | if (err || written != mtd->erasesize) |
105 | printk(PRINT_PREF "error: write failed at %#llx\n", | 105 | pr_err("error: write failed at %#llx\n", |
106 | (long long)addr); | 106 | (long long)addr); |
107 | 107 | ||
108 | return err; | 108 | return err; |
@@ -131,7 +131,7 @@ static int verify_eraseblock(int ebnum) | |||
131 | if (mtd_is_bitflip(err)) | 131 | if (mtd_is_bitflip(err)) |
132 | err = 0; | 132 | err = 0; |
133 | if (err || read != bufsize) { | 133 | if (err || read != bufsize) { |
134 | printk(PRINT_PREF "error: read failed at %#llx\n", | 134 | pr_err("error: read failed at %#llx\n", |
135 | (long long)addr0); | 135 | (long long)addr0); |
136 | return err; | 136 | return err; |
137 | } | 137 | } |
@@ -139,7 +139,7 @@ static int verify_eraseblock(int ebnum) | |||
139 | if (mtd_is_bitflip(err)) | 139 | if (mtd_is_bitflip(err)) |
140 | err = 0; | 140 | err = 0; |
141 | if (err || read != bufsize) { | 141 | if (err || read != bufsize) { |
142 | printk(PRINT_PREF "error: read failed at %#llx\n", | 142 | pr_err("error: read failed at %#llx\n", |
143 | (long long)(addrn - bufsize)); | 143 | (long long)(addrn - bufsize)); |
144 | return err; | 144 | return err; |
145 | } | 145 | } |
@@ -148,12 +148,12 @@ static int verify_eraseblock(int ebnum) | |||
148 | if (mtd_is_bitflip(err)) | 148 | if (mtd_is_bitflip(err)) |
149 | err = 0; | 149 | err = 0; |
150 | if (err || read != bufsize) { | 150 | if (err || read != bufsize) { |
151 | printk(PRINT_PREF "error: read failed at %#llx\n", | 151 | pr_err("error: read failed at %#llx\n", |
152 | (long long)addr); | 152 | (long long)addr); |
153 | break; | 153 | break; |
154 | } | 154 | } |
155 | if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { | 155 | if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { |
156 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 156 | pr_err("error: verify failed at %#llx\n", |
157 | (long long)addr); | 157 | (long long)addr); |
158 | errcnt += 1; | 158 | errcnt += 1; |
159 | } | 159 | } |
@@ -166,7 +166,7 @@ static int verify_eraseblock(int ebnum) | |||
166 | if (mtd_is_bitflip(err)) | 166 | if (mtd_is_bitflip(err)) |
167 | err = 0; | 167 | err = 0; |
168 | if (err || read != bufsize) { | 168 | if (err || read != bufsize) { |
169 | printk(PRINT_PREF "error: read failed at %#llx\n", | 169 | pr_err("error: read failed at %#llx\n", |
170 | (long long)addr0); | 170 | (long long)addr0); |
171 | return err; | 171 | return err; |
172 | } | 172 | } |
@@ -174,7 +174,7 @@ static int verify_eraseblock(int ebnum) | |||
174 | if (mtd_is_bitflip(err)) | 174 | if (mtd_is_bitflip(err)) |
175 | err = 0; | 175 | err = 0; |
176 | if (err || read != bufsize) { | 176 | if (err || read != bufsize) { |
177 | printk(PRINT_PREF "error: read failed at %#llx\n", | 177 | pr_err("error: read failed at %#llx\n", |
178 | (long long)(addrn - bufsize)); | 178 | (long long)(addrn - bufsize)); |
179 | return err; | 179 | return err; |
180 | } | 180 | } |
@@ -183,14 +183,14 @@ static int verify_eraseblock(int ebnum) | |||
183 | if (mtd_is_bitflip(err)) | 183 | if (mtd_is_bitflip(err)) |
184 | err = 0; | 184 | err = 0; |
185 | if (err || read != bufsize) { | 185 | if (err || read != bufsize) { |
186 | printk(PRINT_PREF "error: read failed at %#llx\n", | 186 | pr_err("error: read failed at %#llx\n", |
187 | (long long)addr); | 187 | (long long)addr); |
188 | return err; | 188 | return err; |
189 | } | 189 | } |
190 | memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); | 190 | memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); |
191 | set_random_data(boundary + pgsize, pgsize); | 191 | set_random_data(boundary + pgsize, pgsize); |
192 | if (memcmp(twopages, boundary, bufsize)) { | 192 | if (memcmp(twopages, boundary, bufsize)) { |
193 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 193 | pr_err("error: verify failed at %#llx\n", |
194 | (long long)addr); | 194 | (long long)addr); |
195 | errcnt += 1; | 195 | errcnt += 1; |
196 | } | 196 | } |
@@ -206,10 +206,10 @@ static int crosstest(void) | |||
206 | loff_t addr, addr0, addrn; | 206 | loff_t addr, addr0, addrn; |
207 | unsigned char *pp1, *pp2, *pp3, *pp4; | 207 | unsigned char *pp1, *pp2, *pp3, *pp4; |
208 | 208 | ||
209 | printk(PRINT_PREF "crosstest\n"); | 209 | pr_info("crosstest\n"); |
210 | pp1 = kmalloc(pgsize * 4, GFP_KERNEL); | 210 | pp1 = kmalloc(pgsize * 4, GFP_KERNEL); |
211 | if (!pp1) { | 211 | if (!pp1) { |
212 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 212 | pr_err("error: cannot allocate memory\n"); |
213 | return -ENOMEM; | 213 | return -ENOMEM; |
214 | } | 214 | } |
215 | pp2 = pp1 + pgsize; | 215 | pp2 = pp1 + pgsize; |
@@ -231,7 +231,7 @@ static int crosstest(void) | |||
231 | if (mtd_is_bitflip(err)) | 231 | if (mtd_is_bitflip(err)) |
232 | err = 0; | 232 | err = 0; |
233 | if (err || read != pgsize) { | 233 | if (err || read != pgsize) { |
234 | printk(PRINT_PREF "error: read failed at %#llx\n", | 234 | pr_err("error: read failed at %#llx\n", |
235 | (long long)addr); | 235 | (long long)addr); |
236 | kfree(pp1); | 236 | kfree(pp1); |
237 | return err; | 237 | return err; |
@@ -243,7 +243,7 @@ static int crosstest(void) | |||
243 | if (mtd_is_bitflip(err)) | 243 | if (mtd_is_bitflip(err)) |
244 | err = 0; | 244 | err = 0; |
245 | if (err || read != pgsize) { | 245 | if (err || read != pgsize) { |
246 | printk(PRINT_PREF "error: read failed at %#llx\n", | 246 | pr_err("error: read failed at %#llx\n", |
247 | (long long)addr); | 247 | (long long)addr); |
248 | kfree(pp1); | 248 | kfree(pp1); |
249 | return err; | 249 | return err; |
@@ -251,12 +251,12 @@ static int crosstest(void) | |||
251 | 251 | ||
252 | /* Read first page to pp2 */ | 252 | /* Read first page to pp2 */ |
253 | addr = addr0; | 253 | addr = addr0; |
254 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); | 254 | pr_info("reading page at %#llx\n", (long long)addr); |
255 | err = mtd_read(mtd, addr, pgsize, &read, pp2); | 255 | err = mtd_read(mtd, addr, pgsize, &read, pp2); |
256 | if (mtd_is_bitflip(err)) | 256 | if (mtd_is_bitflip(err)) |
257 | err = 0; | 257 | err = 0; |
258 | if (err || read != pgsize) { | 258 | if (err || read != pgsize) { |
259 | printk(PRINT_PREF "error: read failed at %#llx\n", | 259 | pr_err("error: read failed at %#llx\n", |
260 | (long long)addr); | 260 | (long long)addr); |
261 | kfree(pp1); | 261 | kfree(pp1); |
262 | return err; | 262 | return err; |
@@ -264,12 +264,12 @@ static int crosstest(void) | |||
264 | 264 | ||
265 | /* Read last page to pp3 */ | 265 | /* Read last page to pp3 */ |
266 | addr = addrn - pgsize; | 266 | addr = addrn - pgsize; |
267 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); | 267 | pr_info("reading page at %#llx\n", (long long)addr); |
268 | err = mtd_read(mtd, addr, pgsize, &read, pp3); | 268 | err = mtd_read(mtd, addr, pgsize, &read, pp3); |
269 | if (mtd_is_bitflip(err)) | 269 | if (mtd_is_bitflip(err)) |
270 | err = 0; | 270 | err = 0; |
271 | if (err || read != pgsize) { | 271 | if (err || read != pgsize) { |
272 | printk(PRINT_PREF "error: read failed at %#llx\n", | 272 | pr_err("error: read failed at %#llx\n", |
273 | (long long)addr); | 273 | (long long)addr); |
274 | kfree(pp1); | 274 | kfree(pp1); |
275 | return err; | 275 | return err; |
@@ -277,25 +277,25 @@ static int crosstest(void) | |||
277 | 277 | ||
278 | /* Read first page again to pp4 */ | 278 | /* Read first page again to pp4 */ |
279 | addr = addr0; | 279 | addr = addr0; |
280 | printk(PRINT_PREF "reading page at %#llx\n", (long long)addr); | 280 | pr_info("reading page at %#llx\n", (long long)addr); |
281 | err = mtd_read(mtd, addr, pgsize, &read, pp4); | 281 | err = mtd_read(mtd, addr, pgsize, &read, pp4); |
282 | if (mtd_is_bitflip(err)) | 282 | if (mtd_is_bitflip(err)) |
283 | err = 0; | 283 | err = 0; |
284 | if (err || read != pgsize) { | 284 | if (err || read != pgsize) { |
285 | printk(PRINT_PREF "error: read failed at %#llx\n", | 285 | pr_err("error: read failed at %#llx\n", |
286 | (long long)addr); | 286 | (long long)addr); |
287 | kfree(pp1); | 287 | kfree(pp1); |
288 | return err; | 288 | return err; |
289 | } | 289 | } |
290 | 290 | ||
291 | /* pp2 and pp4 should be the same */ | 291 | /* pp2 and pp4 should be the same */ |
292 | printk(PRINT_PREF "verifying pages read at %#llx match\n", | 292 | pr_info("verifying pages read at %#llx match\n", |
293 | (long long)addr0); | 293 | (long long)addr0); |
294 | if (memcmp(pp2, pp4, pgsize)) { | 294 | if (memcmp(pp2, pp4, pgsize)) { |
295 | printk(PRINT_PREF "verify failed!\n"); | 295 | pr_err("verify failed!\n"); |
296 | errcnt += 1; | 296 | errcnt += 1; |
297 | } else if (!err) | 297 | } else if (!err) |
298 | printk(PRINT_PREF "crosstest ok\n"); | 298 | pr_info("crosstest ok\n"); |
299 | kfree(pp1); | 299 | kfree(pp1); |
300 | return err; | 300 | return err; |
301 | } | 301 | } |
@@ -307,7 +307,7 @@ static int erasecrosstest(void) | |||
307 | loff_t addr0; | 307 | loff_t addr0; |
308 | char *readbuf = twopages; | 308 | char *readbuf = twopages; |
309 | 309 | ||
310 | printk(PRINT_PREF "erasecrosstest\n"); | 310 | pr_info("erasecrosstest\n"); |
311 | 311 | ||
312 | ebnum = 0; | 312 | ebnum = 0; |
313 | addr0 = 0; | 313 | addr0 = 0; |
@@ -320,79 +320,79 @@ static int erasecrosstest(void) | |||
320 | while (ebnum2 && bbt[ebnum2]) | 320 | while (ebnum2 && bbt[ebnum2]) |
321 | ebnum2 -= 1; | 321 | ebnum2 -= 1; |
322 | 322 | ||
323 | printk(PRINT_PREF "erasing block %d\n", ebnum); | 323 | pr_info("erasing block %d\n", ebnum); |
324 | err = erase_eraseblock(ebnum); | 324 | err = erase_eraseblock(ebnum); |
325 | if (err) | 325 | if (err) |
326 | return err; | 326 | return err; |
327 | 327 | ||
328 | printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); | 328 | pr_info("writing 1st page of block %d\n", ebnum); |
329 | set_random_data(writebuf, pgsize); | 329 | set_random_data(writebuf, pgsize); |
330 | strcpy(writebuf, "There is no data like this!"); | 330 | strcpy(writebuf, "There is no data like this!"); |
331 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); | 331 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); |
332 | if (err || written != pgsize) { | 332 | if (err || written != pgsize) { |
333 | printk(PRINT_PREF "error: write failed at %#llx\n", | 333 | pr_info("error: write failed at %#llx\n", |
334 | (long long)addr0); | 334 | (long long)addr0); |
335 | return err ? err : -1; | 335 | return err ? err : -1; |
336 | } | 336 | } |
337 | 337 | ||
338 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); | 338 | pr_info("reading 1st page of block %d\n", ebnum); |
339 | memset(readbuf, 0, pgsize); | 339 | memset(readbuf, 0, pgsize); |
340 | err = mtd_read(mtd, addr0, pgsize, &read, readbuf); | 340 | err = mtd_read(mtd, addr0, pgsize, &read, readbuf); |
341 | if (mtd_is_bitflip(err)) | 341 | if (mtd_is_bitflip(err)) |
342 | err = 0; | 342 | err = 0; |
343 | if (err || read != pgsize) { | 343 | if (err || read != pgsize) { |
344 | printk(PRINT_PREF "error: read failed at %#llx\n", | 344 | pr_err("error: read failed at %#llx\n", |
345 | (long long)addr0); | 345 | (long long)addr0); |
346 | return err ? err : -1; | 346 | return err ? err : -1; |
347 | } | 347 | } |
348 | 348 | ||
349 | printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum); | 349 | pr_info("verifying 1st page of block %d\n", ebnum); |
350 | if (memcmp(writebuf, readbuf, pgsize)) { | 350 | if (memcmp(writebuf, readbuf, pgsize)) { |
351 | printk(PRINT_PREF "verify failed!\n"); | 351 | pr_err("verify failed!\n"); |
352 | errcnt += 1; | 352 | errcnt += 1; |
353 | return -1; | 353 | return -1; |
354 | } | 354 | } |
355 | 355 | ||
356 | printk(PRINT_PREF "erasing block %d\n", ebnum); | 356 | pr_info("erasing block %d\n", ebnum); |
357 | err = erase_eraseblock(ebnum); | 357 | err = erase_eraseblock(ebnum); |
358 | if (err) | 358 | if (err) |
359 | return err; | 359 | return err; |
360 | 360 | ||
361 | printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); | 361 | pr_info("writing 1st page of block %d\n", ebnum); |
362 | set_random_data(writebuf, pgsize); | 362 | set_random_data(writebuf, pgsize); |
363 | strcpy(writebuf, "There is no data like this!"); | 363 | strcpy(writebuf, "There is no data like this!"); |
364 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); | 364 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); |
365 | if (err || written != pgsize) { | 365 | if (err || written != pgsize) { |
366 | printk(PRINT_PREF "error: write failed at %#llx\n", | 366 | pr_err("error: write failed at %#llx\n", |
367 | (long long)addr0); | 367 | (long long)addr0); |
368 | return err ? err : -1; | 368 | return err ? err : -1; |
369 | } | 369 | } |
370 | 370 | ||
371 | printk(PRINT_PREF "erasing block %d\n", ebnum2); | 371 | pr_info("erasing block %d\n", ebnum2); |
372 | err = erase_eraseblock(ebnum2); | 372 | err = erase_eraseblock(ebnum2); |
373 | if (err) | 373 | if (err) |
374 | return err; | 374 | return err; |
375 | 375 | ||
376 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); | 376 | pr_info("reading 1st page of block %d\n", ebnum); |
377 | memset(readbuf, 0, pgsize); | 377 | memset(readbuf, 0, pgsize); |
378 | err = mtd_read(mtd, addr0, pgsize, &read, readbuf); | 378 | err = mtd_read(mtd, addr0, pgsize, &read, readbuf); |
379 | if (mtd_is_bitflip(err)) | 379 | if (mtd_is_bitflip(err)) |
380 | err = 0; | 380 | err = 0; |
381 | if (err || read != pgsize) { | 381 | if (err || read != pgsize) { |
382 | printk(PRINT_PREF "error: read failed at %#llx\n", | 382 | pr_err("error: read failed at %#llx\n", |
383 | (long long)addr0); | 383 | (long long)addr0); |
384 | return err ? err : -1; | 384 | return err ? err : -1; |
385 | } | 385 | } |
386 | 386 | ||
387 | printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum); | 387 | pr_info("verifying 1st page of block %d\n", ebnum); |
388 | if (memcmp(writebuf, readbuf, pgsize)) { | 388 | if (memcmp(writebuf, readbuf, pgsize)) { |
389 | printk(PRINT_PREF "verify failed!\n"); | 389 | pr_err("verify failed!\n"); |
390 | errcnt += 1; | 390 | errcnt += 1; |
391 | return -1; | 391 | return -1; |
392 | } | 392 | } |
393 | 393 | ||
394 | if (!err) | 394 | if (!err) |
395 | printk(PRINT_PREF "erasecrosstest ok\n"); | 395 | pr_info("erasecrosstest ok\n"); |
396 | return err; | 396 | return err; |
397 | } | 397 | } |
398 | 398 | ||
@@ -402,7 +402,7 @@ static int erasetest(void) | |||
402 | int err = 0, i, ebnum, ok = 1; | 402 | int err = 0, i, ebnum, ok = 1; |
403 | loff_t addr0; | 403 | loff_t addr0; |
404 | 404 | ||
405 | printk(PRINT_PREF "erasetest\n"); | 405 | pr_info("erasetest\n"); |
406 | 406 | ||
407 | ebnum = 0; | 407 | ebnum = 0; |
408 | addr0 = 0; | 408 | addr0 = 0; |
@@ -411,40 +411,40 @@ static int erasetest(void) | |||
411 | ebnum += 1; | 411 | ebnum += 1; |
412 | } | 412 | } |
413 | 413 | ||
414 | printk(PRINT_PREF "erasing block %d\n", ebnum); | 414 | pr_info("erasing block %d\n", ebnum); |
415 | err = erase_eraseblock(ebnum); | 415 | err = erase_eraseblock(ebnum); |
416 | if (err) | 416 | if (err) |
417 | return err; | 417 | return err; |
418 | 418 | ||
419 | printk(PRINT_PREF "writing 1st page of block %d\n", ebnum); | 419 | pr_info("writing 1st page of block %d\n", ebnum); |
420 | set_random_data(writebuf, pgsize); | 420 | set_random_data(writebuf, pgsize); |
421 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); | 421 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); |
422 | if (err || written != pgsize) { | 422 | if (err || written != pgsize) { |
423 | printk(PRINT_PREF "error: write failed at %#llx\n", | 423 | pr_err("error: write failed at %#llx\n", |
424 | (long long)addr0); | 424 | (long long)addr0); |
425 | return err ? err : -1; | 425 | return err ? err : -1; |
426 | } | 426 | } |
427 | 427 | ||
428 | printk(PRINT_PREF "erasing block %d\n", ebnum); | 428 | pr_info("erasing block %d\n", ebnum); |
429 | err = erase_eraseblock(ebnum); | 429 | err = erase_eraseblock(ebnum); |
430 | if (err) | 430 | if (err) |
431 | return err; | 431 | return err; |
432 | 432 | ||
433 | printk(PRINT_PREF "reading 1st page of block %d\n", ebnum); | 433 | pr_info("reading 1st page of block %d\n", ebnum); |
434 | err = mtd_read(mtd, addr0, pgsize, &read, twopages); | 434 | err = mtd_read(mtd, addr0, pgsize, &read, twopages); |
435 | if (mtd_is_bitflip(err)) | 435 | if (mtd_is_bitflip(err)) |
436 | err = 0; | 436 | err = 0; |
437 | if (err || read != pgsize) { | 437 | if (err || read != pgsize) { |
438 | printk(PRINT_PREF "error: read failed at %#llx\n", | 438 | pr_err("error: read failed at %#llx\n", |
439 | (long long)addr0); | 439 | (long long)addr0); |
440 | return err ? err : -1; | 440 | return err ? err : -1; |
441 | } | 441 | } |
442 | 442 | ||
443 | printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n", | 443 | pr_info("verifying 1st page of block %d is all 0xff\n", |
444 | ebnum); | 444 | ebnum); |
445 | for (i = 0; i < pgsize; ++i) | 445 | for (i = 0; i < pgsize; ++i) |
446 | if (twopages[i] != 0xff) { | 446 | if (twopages[i] != 0xff) { |
447 | printk(PRINT_PREF "verifying all 0xff failed at %d\n", | 447 | pr_err("verifying all 0xff failed at %d\n", |
448 | i); | 448 | i); |
449 | errcnt += 1; | 449 | errcnt += 1; |
450 | ok = 0; | 450 | ok = 0; |
@@ -452,7 +452,7 @@ static int erasetest(void) | |||
452 | } | 452 | } |
453 | 453 | ||
454 | if (ok && !err) | 454 | if (ok && !err) |
455 | printk(PRINT_PREF "erasetest ok\n"); | 455 | pr_info("erasetest ok\n"); |
456 | 456 | ||
457 | return err; | 457 | return err; |
458 | } | 458 | } |
@@ -464,7 +464,7 @@ static int is_block_bad(int ebnum) | |||
464 | 464 | ||
465 | ret = mtd_block_isbad(mtd, addr); | 465 | ret = mtd_block_isbad(mtd, addr); |
466 | if (ret) | 466 | if (ret) |
467 | printk(PRINT_PREF "block %d is bad\n", ebnum); | 467 | pr_info("block %d is bad\n", ebnum); |
468 | return ret; | 468 | return ret; |
469 | } | 469 | } |
470 | 470 | ||
@@ -474,18 +474,18 @@ static int scan_for_bad_eraseblocks(void) | |||
474 | 474 | ||
475 | bbt = kzalloc(ebcnt, GFP_KERNEL); | 475 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
476 | if (!bbt) { | 476 | if (!bbt) { |
477 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 477 | pr_err("error: cannot allocate memory\n"); |
478 | return -ENOMEM; | 478 | return -ENOMEM; |
479 | } | 479 | } |
480 | 480 | ||
481 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 481 | pr_info("scanning for bad eraseblocks\n"); |
482 | for (i = 0; i < ebcnt; ++i) { | 482 | for (i = 0; i < ebcnt; ++i) { |
483 | bbt[i] = is_block_bad(i) ? 1 : 0; | 483 | bbt[i] = is_block_bad(i) ? 1 : 0; |
484 | if (bbt[i]) | 484 | if (bbt[i]) |
485 | bad += 1; | 485 | bad += 1; |
486 | cond_resched(); | 486 | cond_resched(); |
487 | } | 487 | } |
488 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); | 488 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); |
489 | return 0; | 489 | return 0; |
490 | } | 490 | } |
491 | 491 | ||
@@ -499,22 +499,22 @@ static int __init mtd_pagetest_init(void) | |||
499 | printk(KERN_INFO "=================================================\n"); | 499 | printk(KERN_INFO "=================================================\n"); |
500 | 500 | ||
501 | if (dev < 0) { | 501 | if (dev < 0) { |
502 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | 502 | pr_info("Please specify a valid mtd-device via module parameter\n"); |
503 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | 503 | pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); |
504 | return -EINVAL; | 504 | return -EINVAL; |
505 | } | 505 | } |
506 | 506 | ||
507 | printk(PRINT_PREF "MTD device: %d\n", dev); | 507 | pr_info("MTD device: %d\n", dev); |
508 | 508 | ||
509 | mtd = get_mtd_device(NULL, dev); | 509 | mtd = get_mtd_device(NULL, dev); |
510 | if (IS_ERR(mtd)) { | 510 | if (IS_ERR(mtd)) { |
511 | err = PTR_ERR(mtd); | 511 | err = PTR_ERR(mtd); |
512 | printk(PRINT_PREF "error: cannot get MTD device\n"); | 512 | pr_err("error: cannot get MTD device\n"); |
513 | return err; | 513 | return err; |
514 | } | 514 | } |
515 | 515 | ||
516 | if (mtd->type != MTD_NANDFLASH) { | 516 | if (mtd->type != MTD_NANDFLASH) { |
517 | printk(PRINT_PREF "this test requires NAND flash\n"); | 517 | pr_info("this test requires NAND flash\n"); |
518 | goto out; | 518 | goto out; |
519 | } | 519 | } |
520 | 520 | ||
@@ -524,7 +524,7 @@ static int __init mtd_pagetest_init(void) | |||
524 | pgcnt = mtd->erasesize / mtd->writesize; | 524 | pgcnt = mtd->erasesize / mtd->writesize; |
525 | pgsize = mtd->writesize; | 525 | pgsize = mtd->writesize; |
526 | 526 | ||
527 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 527 | pr_info("MTD device size %llu, eraseblock size %u, " |
528 | "page size %u, count of eraseblocks %u, pages per " | 528 | "page size %u, count of eraseblocks %u, pages per " |
529 | "eraseblock %u, OOB size %u\n", | 529 | "eraseblock %u, OOB size %u\n", |
530 | (unsigned long long)mtd->size, mtd->erasesize, | 530 | (unsigned long long)mtd->size, mtd->erasesize, |
@@ -534,17 +534,17 @@ static int __init mtd_pagetest_init(void) | |||
534 | bufsize = pgsize * 2; | 534 | bufsize = pgsize * 2; |
535 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 535 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
536 | if (!writebuf) { | 536 | if (!writebuf) { |
537 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 537 | pr_err("error: cannot allocate memory\n"); |
538 | goto out; | 538 | goto out; |
539 | } | 539 | } |
540 | twopages = kmalloc(bufsize, GFP_KERNEL); | 540 | twopages = kmalloc(bufsize, GFP_KERNEL); |
541 | if (!twopages) { | 541 | if (!twopages) { |
542 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 542 | pr_err("error: cannot allocate memory\n"); |
543 | goto out; | 543 | goto out; |
544 | } | 544 | } |
545 | boundary = kmalloc(bufsize, GFP_KERNEL); | 545 | boundary = kmalloc(bufsize, GFP_KERNEL); |
546 | if (!boundary) { | 546 | if (!boundary) { |
547 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 547 | pr_err("error: cannot allocate memory\n"); |
548 | goto out; | 548 | goto out; |
549 | } | 549 | } |
550 | 550 | ||
@@ -553,7 +553,7 @@ static int __init mtd_pagetest_init(void) | |||
553 | goto out; | 553 | goto out; |
554 | 554 | ||
555 | /* Erase all eraseblocks */ | 555 | /* Erase all eraseblocks */ |
556 | printk(PRINT_PREF "erasing whole device\n"); | 556 | pr_info("erasing whole device\n"); |
557 | for (i = 0; i < ebcnt; ++i) { | 557 | for (i = 0; i < ebcnt; ++i) { |
558 | if (bbt[i]) | 558 | if (bbt[i]) |
559 | continue; | 559 | continue; |
@@ -562,11 +562,11 @@ static int __init mtd_pagetest_init(void) | |||
562 | goto out; | 562 | goto out; |
563 | cond_resched(); | 563 | cond_resched(); |
564 | } | 564 | } |
565 | printk(PRINT_PREF "erased %u eraseblocks\n", i); | 565 | pr_info("erased %u eraseblocks\n", i); |
566 | 566 | ||
567 | /* Write all eraseblocks */ | 567 | /* Write all eraseblocks */ |
568 | simple_srand(1); | 568 | simple_srand(1); |
569 | printk(PRINT_PREF "writing whole device\n"); | 569 | pr_info("writing whole device\n"); |
570 | for (i = 0; i < ebcnt; ++i) { | 570 | for (i = 0; i < ebcnt; ++i) { |
571 | if (bbt[i]) | 571 | if (bbt[i]) |
572 | continue; | 572 | continue; |
@@ -574,14 +574,14 @@ static int __init mtd_pagetest_init(void) | |||
574 | if (err) | 574 | if (err) |
575 | goto out; | 575 | goto out; |
576 | if (i % 256 == 0) | 576 | if (i % 256 == 0) |
577 | printk(PRINT_PREF "written up to eraseblock %u\n", i); | 577 | pr_info("written up to eraseblock %u\n", i); |
578 | cond_resched(); | 578 | cond_resched(); |
579 | } | 579 | } |
580 | printk(PRINT_PREF "written %u eraseblocks\n", i); | 580 | pr_info("written %u eraseblocks\n", i); |
581 | 581 | ||
582 | /* Check all eraseblocks */ | 582 | /* Check all eraseblocks */ |
583 | simple_srand(1); | 583 | simple_srand(1); |
584 | printk(PRINT_PREF "verifying all eraseblocks\n"); | 584 | pr_info("verifying all eraseblocks\n"); |
585 | for (i = 0; i < ebcnt; ++i) { | 585 | for (i = 0; i < ebcnt; ++i) { |
586 | if (bbt[i]) | 586 | if (bbt[i]) |
587 | continue; | 587 | continue; |
@@ -589,10 +589,10 @@ static int __init mtd_pagetest_init(void) | |||
589 | if (err) | 589 | if (err) |
590 | goto out; | 590 | goto out; |
591 | if (i % 256 == 0) | 591 | if (i % 256 == 0) |
592 | printk(PRINT_PREF "verified up to eraseblock %u\n", i); | 592 | pr_info("verified up to eraseblock %u\n", i); |
593 | cond_resched(); | 593 | cond_resched(); |
594 | } | 594 | } |
595 | printk(PRINT_PREF "verified %u eraseblocks\n", i); | 595 | pr_info("verified %u eraseblocks\n", i); |
596 | 596 | ||
597 | err = crosstest(); | 597 | err = crosstest(); |
598 | if (err) | 598 | if (err) |
@@ -606,7 +606,7 @@ static int __init mtd_pagetest_init(void) | |||
606 | if (err) | 606 | if (err) |
607 | goto out; | 607 | goto out; |
608 | 608 | ||
609 | printk(PRINT_PREF "finished with %d errors\n", errcnt); | 609 | pr_info("finished with %d errors\n", errcnt); |
610 | out: | 610 | out: |
611 | 611 | ||
612 | kfree(bbt); | 612 | kfree(bbt); |
@@ -615,7 +615,7 @@ out: | |||
615 | kfree(writebuf); | 615 | kfree(writebuf); |
616 | put_mtd_device(mtd); | 616 | put_mtd_device(mtd); |
617 | if (err) | 617 | if (err) |
618 | printk(PRINT_PREF "error %d occurred\n", err); | 618 | pr_info("error %d occurred\n", err); |
619 | printk(KERN_INFO "=================================================\n"); | 619 | printk(KERN_INFO "=================================================\n"); |
620 | return err; | 620 | return err; |
621 | } | 621 | } |
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c index 121aba189cec..266de04b6d29 100644 --- a/drivers/mtd/tests/mtd_readtest.c +++ b/drivers/mtd/tests/mtd_readtest.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> | 19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/init.h> | 24 | #include <linux/init.h> |
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
@@ -27,8 +29,6 @@ | |||
27 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
28 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
29 | 31 | ||
30 | #define PRINT_PREF KERN_INFO "mtd_readtest: " | ||
31 | |||
32 | static int dev = -EINVAL; | 32 | static int dev = -EINVAL; |
33 | module_param(dev, int, S_IRUGO); | 33 | module_param(dev, int, S_IRUGO); |
34 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 34 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -51,12 +51,12 @@ static int read_eraseblock_by_page(int ebnum) | |||
51 | void *oobbuf = iobuf1; | 51 | void *oobbuf = iobuf1; |
52 | 52 | ||
53 | for (i = 0; i < pgcnt; i++) { | 53 | for (i = 0; i < pgcnt; i++) { |
54 | memset(buf, 0 , pgcnt); | 54 | memset(buf, 0 , pgsize); |
55 | ret = mtd_read(mtd, addr, pgsize, &read, buf); | 55 | ret = mtd_read(mtd, addr, pgsize, &read, buf); |
56 | if (ret == -EUCLEAN) | 56 | if (ret == -EUCLEAN) |
57 | ret = 0; | 57 | ret = 0; |
58 | if (ret || read != pgsize) { | 58 | if (ret || read != pgsize) { |
59 | printk(PRINT_PREF "error: read failed at %#llx\n", | 59 | pr_err("error: read failed at %#llx\n", |
60 | (long long)addr); | 60 | (long long)addr); |
61 | if (!err) | 61 | if (!err) |
62 | err = ret; | 62 | err = ret; |
@@ -77,7 +77,7 @@ static int read_eraseblock_by_page(int ebnum) | |||
77 | ret = mtd_read_oob(mtd, addr, &ops); | 77 | ret = mtd_read_oob(mtd, addr, &ops); |
78 | if ((ret && !mtd_is_bitflip(ret)) || | 78 | if ((ret && !mtd_is_bitflip(ret)) || |
79 | ops.oobretlen != mtd->oobsize) { | 79 | ops.oobretlen != mtd->oobsize) { |
80 | printk(PRINT_PREF "error: read oob failed at " | 80 | pr_err("error: read oob failed at " |
81 | "%#llx\n", (long long)addr); | 81 | "%#llx\n", (long long)addr); |
82 | if (!err) | 82 | if (!err) |
83 | err = ret; | 83 | err = ret; |
@@ -99,7 +99,7 @@ static void dump_eraseblock(int ebnum) | |||
99 | char line[128]; | 99 | char line[128]; |
100 | int pg, oob; | 100 | int pg, oob; |
101 | 101 | ||
102 | printk(PRINT_PREF "dumping eraseblock %d\n", ebnum); | 102 | pr_info("dumping eraseblock %d\n", ebnum); |
103 | n = mtd->erasesize; | 103 | n = mtd->erasesize; |
104 | for (i = 0; i < n;) { | 104 | for (i = 0; i < n;) { |
105 | char *p = line; | 105 | char *p = line; |
@@ -112,7 +112,7 @@ static void dump_eraseblock(int ebnum) | |||
112 | } | 112 | } |
113 | if (!mtd->oobsize) | 113 | if (!mtd->oobsize) |
114 | return; | 114 | return; |
115 | printk(PRINT_PREF "dumping oob from eraseblock %d\n", ebnum); | 115 | pr_info("dumping oob from eraseblock %d\n", ebnum); |
116 | n = mtd->oobsize; | 116 | n = mtd->oobsize; |
117 | for (pg = 0, i = 0; pg < pgcnt; pg++) | 117 | for (pg = 0, i = 0; pg < pgcnt; pg++) |
118 | for (oob = 0; oob < n;) { | 118 | for (oob = 0; oob < n;) { |
@@ -134,7 +134,7 @@ static int is_block_bad(int ebnum) | |||
134 | 134 | ||
135 | ret = mtd_block_isbad(mtd, addr); | 135 | ret = mtd_block_isbad(mtd, addr); |
136 | if (ret) | 136 | if (ret) |
137 | printk(PRINT_PREF "block %d is bad\n", ebnum); | 137 | pr_info("block %d is bad\n", ebnum); |
138 | return ret; | 138 | return ret; |
139 | } | 139 | } |
140 | 140 | ||
@@ -144,21 +144,21 @@ static int scan_for_bad_eraseblocks(void) | |||
144 | 144 | ||
145 | bbt = kzalloc(ebcnt, GFP_KERNEL); | 145 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
146 | if (!bbt) { | 146 | if (!bbt) { |
147 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 147 | pr_err("error: cannot allocate memory\n"); |
148 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | } | 149 | } |
150 | 150 | ||
151 | if (!mtd_can_have_bb(mtd)) | 151 | if (!mtd_can_have_bb(mtd)) |
152 | return 0; | 152 | return 0; |
153 | 153 | ||
154 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 154 | pr_info("scanning for bad eraseblocks\n"); |
155 | for (i = 0; i < ebcnt; ++i) { | 155 | for (i = 0; i < ebcnt; ++i) { |
156 | bbt[i] = is_block_bad(i) ? 1 : 0; | 156 | bbt[i] = is_block_bad(i) ? 1 : 0; |
157 | if (bbt[i]) | 157 | if (bbt[i]) |
158 | bad += 1; | 158 | bad += 1; |
159 | cond_resched(); | 159 | cond_resched(); |
160 | } | 160 | } |
161 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); | 161 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); |
162 | return 0; | 162 | return 0; |
163 | } | 163 | } |
164 | 164 | ||
@@ -171,21 +171,21 @@ static int __init mtd_readtest_init(void) | |||
171 | printk(KERN_INFO "=================================================\n"); | 171 | printk(KERN_INFO "=================================================\n"); |
172 | 172 | ||
173 | if (dev < 0) { | 173 | if (dev < 0) { |
174 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | 174 | pr_info("Please specify a valid mtd-device via module parameter\n"); |
175 | return -EINVAL; | 175 | return -EINVAL; |
176 | } | 176 | } |
177 | 177 | ||
178 | printk(PRINT_PREF "MTD device: %d\n", dev); | 178 | pr_info("MTD device: %d\n", dev); |
179 | 179 | ||
180 | mtd = get_mtd_device(NULL, dev); | 180 | mtd = get_mtd_device(NULL, dev); |
181 | if (IS_ERR(mtd)) { | 181 | if (IS_ERR(mtd)) { |
182 | err = PTR_ERR(mtd); | 182 | err = PTR_ERR(mtd); |
183 | printk(PRINT_PREF "error: Cannot get MTD device\n"); | 183 | pr_err("error: Cannot get MTD device\n"); |
184 | return err; | 184 | return err; |
185 | } | 185 | } |
186 | 186 | ||
187 | if (mtd->writesize == 1) { | 187 | if (mtd->writesize == 1) { |
188 | printk(PRINT_PREF "not NAND flash, assume page size is 512 " | 188 | pr_info("not NAND flash, assume page size is 512 " |
189 | "bytes.\n"); | 189 | "bytes.\n"); |
190 | pgsize = 512; | 190 | pgsize = 512; |
191 | } else | 191 | } else |
@@ -196,7 +196,7 @@ static int __init mtd_readtest_init(void) | |||
196 | ebcnt = tmp; | 196 | ebcnt = tmp; |
197 | pgcnt = mtd->erasesize / pgsize; | 197 | pgcnt = mtd->erasesize / pgsize; |
198 | 198 | ||
199 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 199 | pr_info("MTD device size %llu, eraseblock size %u, " |
200 | "page size %u, count of eraseblocks %u, pages per " | 200 | "page size %u, count of eraseblocks %u, pages per " |
201 | "eraseblock %u, OOB size %u\n", | 201 | "eraseblock %u, OOB size %u\n", |
202 | (unsigned long long)mtd->size, mtd->erasesize, | 202 | (unsigned long long)mtd->size, mtd->erasesize, |
@@ -205,12 +205,12 @@ static int __init mtd_readtest_init(void) | |||
205 | err = -ENOMEM; | 205 | err = -ENOMEM; |
206 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 206 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
207 | if (!iobuf) { | 207 | if (!iobuf) { |
208 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 208 | pr_err("error: cannot allocate memory\n"); |
209 | goto out; | 209 | goto out; |
210 | } | 210 | } |
211 | iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL); | 211 | iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL); |
212 | if (!iobuf1) { | 212 | if (!iobuf1) { |
213 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 213 | pr_err("error: cannot allocate memory\n"); |
214 | goto out; | 214 | goto out; |
215 | } | 215 | } |
216 | 216 | ||
@@ -219,7 +219,7 @@ static int __init mtd_readtest_init(void) | |||
219 | goto out; | 219 | goto out; |
220 | 220 | ||
221 | /* Read all eraseblocks 1 page at a time */ | 221 | /* Read all eraseblocks 1 page at a time */ |
222 | printk(PRINT_PREF "testing page read\n"); | 222 | pr_info("testing page read\n"); |
223 | for (i = 0; i < ebcnt; ++i) { | 223 | for (i = 0; i < ebcnt; ++i) { |
224 | int ret; | 224 | int ret; |
225 | 225 | ||
@@ -235,9 +235,9 @@ static int __init mtd_readtest_init(void) | |||
235 | } | 235 | } |
236 | 236 | ||
237 | if (err) | 237 | if (err) |
238 | printk(PRINT_PREF "finished with errors\n"); | 238 | pr_info("finished with errors\n"); |
239 | else | 239 | else |
240 | printk(PRINT_PREF "finished\n"); | 240 | pr_info("finished\n"); |
241 | 241 | ||
242 | out: | 242 | out: |
243 | 243 | ||
@@ -246,7 +246,7 @@ out: | |||
246 | kfree(bbt); | 246 | kfree(bbt); |
247 | put_mtd_device(mtd); | 247 | put_mtd_device(mtd); |
248 | if (err) | 248 | if (err) |
249 | printk(PRINT_PREF "error %d occurred\n", err); | 249 | pr_info("error %d occurred\n", err); |
250 | printk(KERN_INFO "=================================================\n"); | 250 | printk(KERN_INFO "=================================================\n"); |
251 | return err; | 251 | return err; |
252 | } | 252 | } |
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 42b0f7456fc4..596cbea8df4c 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * Author: Adrian Hunter <adrian.hunter@nokia.com> | 19 | * Author: Adrian Hunter <adrian.hunter@nokia.com> |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/init.h> | 24 | #include <linux/init.h> |
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
@@ -28,8 +30,6 @@ | |||
28 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
29 | #include <linux/random.h> | 31 | #include <linux/random.h> |
30 | 32 | ||
31 | #define PRINT_PREF KERN_INFO "mtd_speedtest: " | ||
32 | |||
33 | static int dev = -EINVAL; | 33 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 34 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 35 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -70,12 +70,12 @@ static int erase_eraseblock(int ebnum) | |||
70 | 70 | ||
71 | err = mtd_erase(mtd, &ei); | 71 | err = mtd_erase(mtd, &ei); |
72 | if (err) { | 72 | if (err) { |
73 | printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); | 73 | pr_err("error %d while erasing EB %d\n", err, ebnum); |
74 | return err; | 74 | return err; |
75 | } | 75 | } |
76 | 76 | ||
77 | if (ei.state == MTD_ERASE_FAILED) { | 77 | if (ei.state == MTD_ERASE_FAILED) { |
78 | printk(PRINT_PREF "some erase error occurred at EB %d\n", | 78 | pr_err("some erase error occurred at EB %d\n", |
79 | ebnum); | 79 | ebnum); |
80 | return -EIO; | 80 | return -EIO; |
81 | } | 81 | } |
@@ -96,13 +96,13 @@ static int multiblock_erase(int ebnum, int blocks) | |||
96 | 96 | ||
97 | err = mtd_erase(mtd, &ei); | 97 | err = mtd_erase(mtd, &ei); |
98 | if (err) { | 98 | if (err) { |
99 | printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n", | 99 | pr_err("error %d while erasing EB %d, blocks %d\n", |
100 | err, ebnum, blocks); | 100 | err, ebnum, blocks); |
101 | return err; | 101 | return err; |
102 | } | 102 | } |
103 | 103 | ||
104 | if (ei.state == MTD_ERASE_FAILED) { | 104 | if (ei.state == MTD_ERASE_FAILED) { |
105 | printk(PRINT_PREF "some erase error occurred at EB %d," | 105 | pr_err("some erase error occurred at EB %d," |
106 | "blocks %d\n", ebnum, blocks); | 106 | "blocks %d\n", ebnum, blocks); |
107 | return -EIO; | 107 | return -EIO; |
108 | } | 108 | } |
@@ -134,7 +134,7 @@ static int write_eraseblock(int ebnum) | |||
134 | 134 | ||
135 | err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf); | 135 | err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf); |
136 | if (err || written != mtd->erasesize) { | 136 | if (err || written != mtd->erasesize) { |
137 | printk(PRINT_PREF "error: write failed at %#llx\n", addr); | 137 | pr_err("error: write failed at %#llx\n", addr); |
138 | if (!err) | 138 | if (!err) |
139 | err = -EINVAL; | 139 | err = -EINVAL; |
140 | } | 140 | } |
@@ -152,7 +152,7 @@ static int write_eraseblock_by_page(int ebnum) | |||
152 | for (i = 0; i < pgcnt; i++) { | 152 | for (i = 0; i < pgcnt; i++) { |
153 | err = mtd_write(mtd, addr, pgsize, &written, buf); | 153 | err = mtd_write(mtd, addr, pgsize, &written, buf); |
154 | if (err || written != pgsize) { | 154 | if (err || written != pgsize) { |
155 | printk(PRINT_PREF "error: write failed at %#llx\n", | 155 | pr_err("error: write failed at %#llx\n", |
156 | addr); | 156 | addr); |
157 | if (!err) | 157 | if (!err) |
158 | err = -EINVAL; | 158 | err = -EINVAL; |
@@ -175,7 +175,7 @@ static int write_eraseblock_by_2pages(int ebnum) | |||
175 | for (i = 0; i < n; i++) { | 175 | for (i = 0; i < n; i++) { |
176 | err = mtd_write(mtd, addr, sz, &written, buf); | 176 | err = mtd_write(mtd, addr, sz, &written, buf); |
177 | if (err || written != sz) { | 177 | if (err || written != sz) { |
178 | printk(PRINT_PREF "error: write failed at %#llx\n", | 178 | pr_err("error: write failed at %#llx\n", |
179 | addr); | 179 | addr); |
180 | if (!err) | 180 | if (!err) |
181 | err = -EINVAL; | 181 | err = -EINVAL; |
@@ -187,7 +187,7 @@ static int write_eraseblock_by_2pages(int ebnum) | |||
187 | if (pgcnt % 2) { | 187 | if (pgcnt % 2) { |
188 | err = mtd_write(mtd, addr, pgsize, &written, buf); | 188 | err = mtd_write(mtd, addr, pgsize, &written, buf); |
189 | if (err || written != pgsize) { | 189 | if (err || written != pgsize) { |
190 | printk(PRINT_PREF "error: write failed at %#llx\n", | 190 | pr_err("error: write failed at %#llx\n", |
191 | addr); | 191 | addr); |
192 | if (!err) | 192 | if (!err) |
193 | err = -EINVAL; | 193 | err = -EINVAL; |
@@ -208,7 +208,7 @@ static int read_eraseblock(int ebnum) | |||
208 | if (mtd_is_bitflip(err)) | 208 | if (mtd_is_bitflip(err)) |
209 | err = 0; | 209 | err = 0; |
210 | if (err || read != mtd->erasesize) { | 210 | if (err || read != mtd->erasesize) { |
211 | printk(PRINT_PREF "error: read failed at %#llx\n", addr); | 211 | pr_err("error: read failed at %#llx\n", addr); |
212 | if (!err) | 212 | if (!err) |
213 | err = -EINVAL; | 213 | err = -EINVAL; |
214 | } | 214 | } |
@@ -229,7 +229,7 @@ static int read_eraseblock_by_page(int ebnum) | |||
229 | if (mtd_is_bitflip(err)) | 229 | if (mtd_is_bitflip(err)) |
230 | err = 0; | 230 | err = 0; |
231 | if (err || read != pgsize) { | 231 | if (err || read != pgsize) { |
232 | printk(PRINT_PREF "error: read failed at %#llx\n", | 232 | pr_err("error: read failed at %#llx\n", |
233 | addr); | 233 | addr); |
234 | if (!err) | 234 | if (!err) |
235 | err = -EINVAL; | 235 | err = -EINVAL; |
@@ -255,7 +255,7 @@ static int read_eraseblock_by_2pages(int ebnum) | |||
255 | if (mtd_is_bitflip(err)) | 255 | if (mtd_is_bitflip(err)) |
256 | err = 0; | 256 | err = 0; |
257 | if (err || read != sz) { | 257 | if (err || read != sz) { |
258 | printk(PRINT_PREF "error: read failed at %#llx\n", | 258 | pr_err("error: read failed at %#llx\n", |
259 | addr); | 259 | addr); |
260 | if (!err) | 260 | if (!err) |
261 | err = -EINVAL; | 261 | err = -EINVAL; |
@@ -270,7 +270,7 @@ static int read_eraseblock_by_2pages(int ebnum) | |||
270 | if (mtd_is_bitflip(err)) | 270 | if (mtd_is_bitflip(err)) |
271 | err = 0; | 271 | err = 0; |
272 | if (err || read != pgsize) { | 272 | if (err || read != pgsize) { |
273 | printk(PRINT_PREF "error: read failed at %#llx\n", | 273 | pr_err("error: read failed at %#llx\n", |
274 | addr); | 274 | addr); |
275 | if (!err) | 275 | if (!err) |
276 | err = -EINVAL; | 276 | err = -EINVAL; |
@@ -287,7 +287,7 @@ static int is_block_bad(int ebnum) | |||
287 | 287 | ||
288 | ret = mtd_block_isbad(mtd, addr); | 288 | ret = mtd_block_isbad(mtd, addr); |
289 | if (ret) | 289 | if (ret) |
290 | printk(PRINT_PREF "block %d is bad\n", ebnum); | 290 | pr_info("block %d is bad\n", ebnum); |
291 | return ret; | 291 | return ret; |
292 | } | 292 | } |
293 | 293 | ||
@@ -321,21 +321,21 @@ static int scan_for_bad_eraseblocks(void) | |||
321 | 321 | ||
322 | bbt = kzalloc(ebcnt, GFP_KERNEL); | 322 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
323 | if (!bbt) { | 323 | if (!bbt) { |
324 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 324 | pr_err("error: cannot allocate memory\n"); |
325 | return -ENOMEM; | 325 | return -ENOMEM; |
326 | } | 326 | } |
327 | 327 | ||
328 | if (!mtd_can_have_bb(mtd)) | 328 | if (!mtd_can_have_bb(mtd)) |
329 | goto out; | 329 | goto out; |
330 | 330 | ||
331 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 331 | pr_info("scanning for bad eraseblocks\n"); |
332 | for (i = 0; i < ebcnt; ++i) { | 332 | for (i = 0; i < ebcnt; ++i) { |
333 | bbt[i] = is_block_bad(i) ? 1 : 0; | 333 | bbt[i] = is_block_bad(i) ? 1 : 0; |
334 | if (bbt[i]) | 334 | if (bbt[i]) |
335 | bad += 1; | 335 | bad += 1; |
336 | cond_resched(); | 336 | cond_resched(); |
337 | } | 337 | } |
338 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); | 338 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); |
339 | out: | 339 | out: |
340 | goodebcnt = ebcnt - bad; | 340 | goodebcnt = ebcnt - bad; |
341 | return 0; | 341 | return 0; |
@@ -351,25 +351,25 @@ static int __init mtd_speedtest_init(void) | |||
351 | printk(KERN_INFO "=================================================\n"); | 351 | printk(KERN_INFO "=================================================\n"); |
352 | 352 | ||
353 | if (dev < 0) { | 353 | if (dev < 0) { |
354 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | 354 | pr_info("Please specify a valid mtd-device via module parameter\n"); |
355 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | 355 | pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); |
356 | return -EINVAL; | 356 | return -EINVAL; |
357 | } | 357 | } |
358 | 358 | ||
359 | if (count) | 359 | if (count) |
360 | printk(PRINT_PREF "MTD device: %d count: %d\n", dev, count); | 360 | pr_info("MTD device: %d count: %d\n", dev, count); |
361 | else | 361 | else |
362 | printk(PRINT_PREF "MTD device: %d\n", dev); | 362 | pr_info("MTD device: %d\n", dev); |
363 | 363 | ||
364 | mtd = get_mtd_device(NULL, dev); | 364 | mtd = get_mtd_device(NULL, dev); |
365 | if (IS_ERR(mtd)) { | 365 | if (IS_ERR(mtd)) { |
366 | err = PTR_ERR(mtd); | 366 | err = PTR_ERR(mtd); |
367 | printk(PRINT_PREF "error: cannot get MTD device\n"); | 367 | pr_err("error: cannot get MTD device\n"); |
368 | return err; | 368 | return err; |
369 | } | 369 | } |
370 | 370 | ||
371 | if (mtd->writesize == 1) { | 371 | if (mtd->writesize == 1) { |
372 | printk(PRINT_PREF "not NAND flash, assume page size is 512 " | 372 | pr_info("not NAND flash, assume page size is 512 " |
373 | "bytes.\n"); | 373 | "bytes.\n"); |
374 | pgsize = 512; | 374 | pgsize = 512; |
375 | } else | 375 | } else |
@@ -380,7 +380,7 @@ static int __init mtd_speedtest_init(void) | |||
380 | ebcnt = tmp; | 380 | ebcnt = tmp; |
381 | pgcnt = mtd->erasesize / pgsize; | 381 | pgcnt = mtd->erasesize / pgsize; |
382 | 382 | ||
383 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 383 | pr_info("MTD device size %llu, eraseblock size %u, " |
384 | "page size %u, count of eraseblocks %u, pages per " | 384 | "page size %u, count of eraseblocks %u, pages per " |
385 | "eraseblock %u, OOB size %u\n", | 385 | "eraseblock %u, OOB size %u\n", |
386 | (unsigned long long)mtd->size, mtd->erasesize, | 386 | (unsigned long long)mtd->size, mtd->erasesize, |
@@ -392,7 +392,7 @@ static int __init mtd_speedtest_init(void) | |||
392 | err = -ENOMEM; | 392 | err = -ENOMEM; |
393 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 393 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
394 | if (!iobuf) { | 394 | if (!iobuf) { |
395 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 395 | pr_err("error: cannot allocate memory\n"); |
396 | goto out; | 396 | goto out; |
397 | } | 397 | } |
398 | 398 | ||
@@ -407,7 +407,7 @@ static int __init mtd_speedtest_init(void) | |||
407 | goto out; | 407 | goto out; |
408 | 408 | ||
409 | /* Write all eraseblocks, 1 eraseblock at a time */ | 409 | /* Write all eraseblocks, 1 eraseblock at a time */ |
410 | printk(PRINT_PREF "testing eraseblock write speed\n"); | 410 | pr_info("testing eraseblock write speed\n"); |
411 | start_timing(); | 411 | start_timing(); |
412 | for (i = 0; i < ebcnt; ++i) { | 412 | for (i = 0; i < ebcnt; ++i) { |
413 | if (bbt[i]) | 413 | if (bbt[i]) |
@@ -419,10 +419,10 @@ static int __init mtd_speedtest_init(void) | |||
419 | } | 419 | } |
420 | stop_timing(); | 420 | stop_timing(); |
421 | speed = calc_speed(); | 421 | speed = calc_speed(); |
422 | printk(PRINT_PREF "eraseblock write speed is %ld KiB/s\n", speed); | 422 | pr_info("eraseblock write speed is %ld KiB/s\n", speed); |
423 | 423 | ||
424 | /* Read all eraseblocks, 1 eraseblock at a time */ | 424 | /* Read all eraseblocks, 1 eraseblock at a time */ |
425 | printk(PRINT_PREF "testing eraseblock read speed\n"); | 425 | pr_info("testing eraseblock read speed\n"); |
426 | start_timing(); | 426 | start_timing(); |
427 | for (i = 0; i < ebcnt; ++i) { | 427 | for (i = 0; i < ebcnt; ++i) { |
428 | if (bbt[i]) | 428 | if (bbt[i]) |
@@ -434,14 +434,14 @@ static int __init mtd_speedtest_init(void) | |||
434 | } | 434 | } |
435 | stop_timing(); | 435 | stop_timing(); |
436 | speed = calc_speed(); | 436 | speed = calc_speed(); |
437 | printk(PRINT_PREF "eraseblock read speed is %ld KiB/s\n", speed); | 437 | pr_info("eraseblock read speed is %ld KiB/s\n", speed); |
438 | 438 | ||
439 | err = erase_whole_device(); | 439 | err = erase_whole_device(); |
440 | if (err) | 440 | if (err) |
441 | goto out; | 441 | goto out; |
442 | 442 | ||
443 | /* Write all eraseblocks, 1 page at a time */ | 443 | /* Write all eraseblocks, 1 page at a time */ |
444 | printk(PRINT_PREF "testing page write speed\n"); | 444 | pr_info("testing page write speed\n"); |
445 | start_timing(); | 445 | start_timing(); |
446 | for (i = 0; i < ebcnt; ++i) { | 446 | for (i = 0; i < ebcnt; ++i) { |
447 | if (bbt[i]) | 447 | if (bbt[i]) |
@@ -453,10 +453,10 @@ static int __init mtd_speedtest_init(void) | |||
453 | } | 453 | } |
454 | stop_timing(); | 454 | stop_timing(); |
455 | speed = calc_speed(); | 455 | speed = calc_speed(); |
456 | printk(PRINT_PREF "page write speed is %ld KiB/s\n", speed); | 456 | pr_info("page write speed is %ld KiB/s\n", speed); |
457 | 457 | ||
458 | /* Read all eraseblocks, 1 page at a time */ | 458 | /* Read all eraseblocks, 1 page at a time */ |
459 | printk(PRINT_PREF "testing page read speed\n"); | 459 | pr_info("testing page read speed\n"); |
460 | start_timing(); | 460 | start_timing(); |
461 | for (i = 0; i < ebcnt; ++i) { | 461 | for (i = 0; i < ebcnt; ++i) { |
462 | if (bbt[i]) | 462 | if (bbt[i]) |
@@ -468,14 +468,14 @@ static int __init mtd_speedtest_init(void) | |||
468 | } | 468 | } |
469 | stop_timing(); | 469 | stop_timing(); |
470 | speed = calc_speed(); | 470 | speed = calc_speed(); |
471 | printk(PRINT_PREF "page read speed is %ld KiB/s\n", speed); | 471 | pr_info("page read speed is %ld KiB/s\n", speed); |
472 | 472 | ||
473 | err = erase_whole_device(); | 473 | err = erase_whole_device(); |
474 | if (err) | 474 | if (err) |
475 | goto out; | 475 | goto out; |
476 | 476 | ||
477 | /* Write all eraseblocks, 2 pages at a time */ | 477 | /* Write all eraseblocks, 2 pages at a time */ |
478 | printk(PRINT_PREF "testing 2 page write speed\n"); | 478 | pr_info("testing 2 page write speed\n"); |
479 | start_timing(); | 479 | start_timing(); |
480 | for (i = 0; i < ebcnt; ++i) { | 480 | for (i = 0; i < ebcnt; ++i) { |
481 | if (bbt[i]) | 481 | if (bbt[i]) |
@@ -487,10 +487,10 @@ static int __init mtd_speedtest_init(void) | |||
487 | } | 487 | } |
488 | stop_timing(); | 488 | stop_timing(); |
489 | speed = calc_speed(); | 489 | speed = calc_speed(); |
490 | printk(PRINT_PREF "2 page write speed is %ld KiB/s\n", speed); | 490 | pr_info("2 page write speed is %ld KiB/s\n", speed); |
491 | 491 | ||
492 | /* Read all eraseblocks, 2 pages at a time */ | 492 | /* Read all eraseblocks, 2 pages at a time */ |
493 | printk(PRINT_PREF "testing 2 page read speed\n"); | 493 | pr_info("testing 2 page read speed\n"); |
494 | start_timing(); | 494 | start_timing(); |
495 | for (i = 0; i < ebcnt; ++i) { | 495 | for (i = 0; i < ebcnt; ++i) { |
496 | if (bbt[i]) | 496 | if (bbt[i]) |
@@ -502,10 +502,10 @@ static int __init mtd_speedtest_init(void) | |||
502 | } | 502 | } |
503 | stop_timing(); | 503 | stop_timing(); |
504 | speed = calc_speed(); | 504 | speed = calc_speed(); |
505 | printk(PRINT_PREF "2 page read speed is %ld KiB/s\n", speed); | 505 | pr_info("2 page read speed is %ld KiB/s\n", speed); |
506 | 506 | ||
507 | /* Erase all eraseblocks */ | 507 | /* Erase all eraseblocks */ |
508 | printk(PRINT_PREF "Testing erase speed\n"); | 508 | pr_info("Testing erase speed\n"); |
509 | start_timing(); | 509 | start_timing(); |
510 | for (i = 0; i < ebcnt; ++i) { | 510 | for (i = 0; i < ebcnt; ++i) { |
511 | if (bbt[i]) | 511 | if (bbt[i]) |
@@ -517,12 +517,12 @@ static int __init mtd_speedtest_init(void) | |||
517 | } | 517 | } |
518 | stop_timing(); | 518 | stop_timing(); |
519 | speed = calc_speed(); | 519 | speed = calc_speed(); |
520 | printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed); | 520 | pr_info("erase speed is %ld KiB/s\n", speed); |
521 | 521 | ||
522 | /* Multi-block erase all eraseblocks */ | 522 | /* Multi-block erase all eraseblocks */ |
523 | for (k = 1; k < 7; k++) { | 523 | for (k = 1; k < 7; k++) { |
524 | blocks = 1 << k; | 524 | blocks = 1 << k; |
525 | printk(PRINT_PREF "Testing %dx multi-block erase speed\n", | 525 | pr_info("Testing %dx multi-block erase speed\n", |
526 | blocks); | 526 | blocks); |
527 | start_timing(); | 527 | start_timing(); |
528 | for (i = 0; i < ebcnt; ) { | 528 | for (i = 0; i < ebcnt; ) { |
@@ -541,16 +541,16 @@ static int __init mtd_speedtest_init(void) | |||
541 | } | 541 | } |
542 | stop_timing(); | 542 | stop_timing(); |
543 | speed = calc_speed(); | 543 | speed = calc_speed(); |
544 | printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n", | 544 | pr_info("%dx multi-block erase speed is %ld KiB/s\n", |
545 | blocks, speed); | 545 | blocks, speed); |
546 | } | 546 | } |
547 | printk(PRINT_PREF "finished\n"); | 547 | pr_info("finished\n"); |
548 | out: | 548 | out: |
549 | kfree(iobuf); | 549 | kfree(iobuf); |
550 | kfree(bbt); | 550 | kfree(bbt); |
551 | put_mtd_device(mtd); | 551 | put_mtd_device(mtd); |
552 | if (err) | 552 | if (err) |
553 | printk(PRINT_PREF "error %d occurred\n", err); | 553 | pr_info("error %d occurred\n", err); |
554 | printk(KERN_INFO "=================================================\n"); | 554 | printk(KERN_INFO "=================================================\n"); |
555 | return err; | 555 | return err; |
556 | } | 556 | } |
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c index cb268cebf01a..3729f679ae5d 100644 --- a/drivers/mtd/tests/mtd_stresstest.c +++ b/drivers/mtd/tests/mtd_stresstest.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> | 19 | * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/init.h> | 24 | #include <linux/init.h> |
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
@@ -29,8 +31,6 @@ | |||
29 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
30 | #include <linux/random.h> | 32 | #include <linux/random.h> |
31 | 33 | ||
32 | #define PRINT_PREF KERN_INFO "mtd_stresstest: " | ||
33 | |||
34 | static int dev = -EINVAL; | 34 | static int dev = -EINVAL; |
35 | module_param(dev, int, S_IRUGO); | 35 | module_param(dev, int, S_IRUGO); |
36 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 36 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -94,12 +94,12 @@ static int erase_eraseblock(int ebnum) | |||
94 | 94 | ||
95 | err = mtd_erase(mtd, &ei); | 95 | err = mtd_erase(mtd, &ei); |
96 | if (unlikely(err)) { | 96 | if (unlikely(err)) { |
97 | printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); | 97 | pr_err("error %d while erasing EB %d\n", err, ebnum); |
98 | return err; | 98 | return err; |
99 | } | 99 | } |
100 | 100 | ||
101 | if (unlikely(ei.state == MTD_ERASE_FAILED)) { | 101 | if (unlikely(ei.state == MTD_ERASE_FAILED)) { |
102 | printk(PRINT_PREF "some erase error occurred at EB %d\n", | 102 | pr_err("some erase error occurred at EB %d\n", |
103 | ebnum); | 103 | ebnum); |
104 | return -EIO; | 104 | return -EIO; |
105 | } | 105 | } |
@@ -114,7 +114,7 @@ static int is_block_bad(int ebnum) | |||
114 | 114 | ||
115 | ret = mtd_block_isbad(mtd, addr); | 115 | ret = mtd_block_isbad(mtd, addr); |
116 | if (ret) | 116 | if (ret) |
117 | printk(PRINT_PREF "block %d is bad\n", ebnum); | 117 | pr_info("block %d is bad\n", ebnum); |
118 | return ret; | 118 | return ret; |
119 | } | 119 | } |
120 | 120 | ||
@@ -137,7 +137,7 @@ static int do_read(void) | |||
137 | if (mtd_is_bitflip(err)) | 137 | if (mtd_is_bitflip(err)) |
138 | err = 0; | 138 | err = 0; |
139 | if (unlikely(err || read != len)) { | 139 | if (unlikely(err || read != len)) { |
140 | printk(PRINT_PREF "error: read failed at 0x%llx\n", | 140 | pr_err("error: read failed at 0x%llx\n", |
141 | (long long)addr); | 141 | (long long)addr); |
142 | if (!err) | 142 | if (!err) |
143 | err = -EINVAL; | 143 | err = -EINVAL; |
@@ -174,7 +174,7 @@ static int do_write(void) | |||
174 | addr = eb * mtd->erasesize + offs; | 174 | addr = eb * mtd->erasesize + offs; |
175 | err = mtd_write(mtd, addr, len, &written, writebuf); | 175 | err = mtd_write(mtd, addr, len, &written, writebuf); |
176 | if (unlikely(err || written != len)) { | 176 | if (unlikely(err || written != len)) { |
177 | printk(PRINT_PREF "error: write failed at 0x%llx\n", | 177 | pr_err("error: write failed at 0x%llx\n", |
178 | (long long)addr); | 178 | (long long)addr); |
179 | if (!err) | 179 | if (!err) |
180 | err = -EINVAL; | 180 | err = -EINVAL; |
@@ -203,21 +203,21 @@ static int scan_for_bad_eraseblocks(void) | |||
203 | 203 | ||
204 | bbt = kzalloc(ebcnt, GFP_KERNEL); | 204 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
205 | if (!bbt) { | 205 | if (!bbt) { |
206 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 206 | pr_err("error: cannot allocate memory\n"); |
207 | return -ENOMEM; | 207 | return -ENOMEM; |
208 | } | 208 | } |
209 | 209 | ||
210 | if (!mtd_can_have_bb(mtd)) | 210 | if (!mtd_can_have_bb(mtd)) |
211 | return 0; | 211 | return 0; |
212 | 212 | ||
213 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 213 | pr_info("scanning for bad eraseblocks\n"); |
214 | for (i = 0; i < ebcnt; ++i) { | 214 | for (i = 0; i < ebcnt; ++i) { |
215 | bbt[i] = is_block_bad(i) ? 1 : 0; | 215 | bbt[i] = is_block_bad(i) ? 1 : 0; |
216 | if (bbt[i]) | 216 | if (bbt[i]) |
217 | bad += 1; | 217 | bad += 1; |
218 | cond_resched(); | 218 | cond_resched(); |
219 | } | 219 | } |
220 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); | 220 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); |
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | 223 | ||
@@ -231,22 +231,22 @@ static int __init mtd_stresstest_init(void) | |||
231 | printk(KERN_INFO "=================================================\n"); | 231 | printk(KERN_INFO "=================================================\n"); |
232 | 232 | ||
233 | if (dev < 0) { | 233 | if (dev < 0) { |
234 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | 234 | pr_info("Please specify a valid mtd-device via module parameter\n"); |
235 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | 235 | pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); |
236 | return -EINVAL; | 236 | return -EINVAL; |
237 | } | 237 | } |
238 | 238 | ||
239 | printk(PRINT_PREF "MTD device: %d\n", dev); | 239 | pr_info("MTD device: %d\n", dev); |
240 | 240 | ||
241 | mtd = get_mtd_device(NULL, dev); | 241 | mtd = get_mtd_device(NULL, dev); |
242 | if (IS_ERR(mtd)) { | 242 | if (IS_ERR(mtd)) { |
243 | err = PTR_ERR(mtd); | 243 | err = PTR_ERR(mtd); |
244 | printk(PRINT_PREF "error: cannot get MTD device\n"); | 244 | pr_err("error: cannot get MTD device\n"); |
245 | return err; | 245 | return err; |
246 | } | 246 | } |
247 | 247 | ||
248 | if (mtd->writesize == 1) { | 248 | if (mtd->writesize == 1) { |
249 | printk(PRINT_PREF "not NAND flash, assume page size is 512 " | 249 | pr_info("not NAND flash, assume page size is 512 " |
250 | "bytes.\n"); | 250 | "bytes.\n"); |
251 | pgsize = 512; | 251 | pgsize = 512; |
252 | } else | 252 | } else |
@@ -257,14 +257,14 @@ static int __init mtd_stresstest_init(void) | |||
257 | ebcnt = tmp; | 257 | ebcnt = tmp; |
258 | pgcnt = mtd->erasesize / pgsize; | 258 | pgcnt = mtd->erasesize / pgsize; |
259 | 259 | ||
260 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 260 | pr_info("MTD device size %llu, eraseblock size %u, " |
261 | "page size %u, count of eraseblocks %u, pages per " | 261 | "page size %u, count of eraseblocks %u, pages per " |
262 | "eraseblock %u, OOB size %u\n", | 262 | "eraseblock %u, OOB size %u\n", |
263 | (unsigned long long)mtd->size, mtd->erasesize, | 263 | (unsigned long long)mtd->size, mtd->erasesize, |
264 | pgsize, ebcnt, pgcnt, mtd->oobsize); | 264 | pgsize, ebcnt, pgcnt, mtd->oobsize); |
265 | 265 | ||
266 | if (ebcnt < 2) { | 266 | if (ebcnt < 2) { |
267 | printk(PRINT_PREF "error: need at least 2 eraseblocks\n"); | 267 | pr_err("error: need at least 2 eraseblocks\n"); |
268 | err = -ENOSPC; | 268 | err = -ENOSPC; |
269 | goto out_put_mtd; | 269 | goto out_put_mtd; |
270 | } | 270 | } |
@@ -277,7 +277,7 @@ static int __init mtd_stresstest_init(void) | |||
277 | writebuf = vmalloc(bufsize); | 277 | writebuf = vmalloc(bufsize); |
278 | offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL); | 278 | offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL); |
279 | if (!readbuf || !writebuf || !offsets) { | 279 | if (!readbuf || !writebuf || !offsets) { |
280 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 280 | pr_err("error: cannot allocate memory\n"); |
281 | goto out; | 281 | goto out; |
282 | } | 282 | } |
283 | for (i = 0; i < ebcnt; i++) | 283 | for (i = 0; i < ebcnt; i++) |
@@ -290,16 +290,16 @@ static int __init mtd_stresstest_init(void) | |||
290 | goto out; | 290 | goto out; |
291 | 291 | ||
292 | /* Do operations */ | 292 | /* Do operations */ |
293 | printk(PRINT_PREF "doing operations\n"); | 293 | pr_info("doing operations\n"); |
294 | for (op = 0; op < count; op++) { | 294 | for (op = 0; op < count; op++) { |
295 | if ((op & 1023) == 0) | 295 | if ((op & 1023) == 0) |
296 | printk(PRINT_PREF "%d operations done\n", op); | 296 | pr_info("%d operations done\n", op); |
297 | err = do_operation(); | 297 | err = do_operation(); |
298 | if (err) | 298 | if (err) |
299 | goto out; | 299 | goto out; |
300 | cond_resched(); | 300 | cond_resched(); |
301 | } | 301 | } |
302 | printk(PRINT_PREF "finished, %d operations done\n", op); | 302 | pr_info("finished, %d operations done\n", op); |
303 | 303 | ||
304 | out: | 304 | out: |
305 | kfree(offsets); | 305 | kfree(offsets); |
@@ -309,7 +309,7 @@ out: | |||
309 | out_put_mtd: | 309 | out_put_mtd: |
310 | put_mtd_device(mtd); | 310 | put_mtd_device(mtd); |
311 | if (err) | 311 | if (err) |
312 | printk(PRINT_PREF "error %d occurred\n", err); | 312 | pr_info("error %d occurred\n", err); |
313 | printk(KERN_INFO "=================================================\n"); | 313 | printk(KERN_INFO "=================================================\n"); |
314 | return err; | 314 | return err; |
315 | } | 315 | } |
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c index 9667bf535282..c880c2229c59 100644 --- a/drivers/mtd/tests/mtd_subpagetest.c +++ b/drivers/mtd/tests/mtd_subpagetest.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/init.h> | 24 | #include <linux/init.h> |
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
@@ -27,8 +29,6 @@ | |||
27 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
28 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
29 | 31 | ||
30 | #define PRINT_PREF KERN_INFO "mtd_subpagetest: " | ||
31 | |||
32 | static int dev = -EINVAL; | 32 | static int dev = -EINVAL; |
33 | module_param(dev, int, S_IRUGO); | 33 | module_param(dev, int, S_IRUGO); |
34 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 34 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -82,12 +82,12 @@ static int erase_eraseblock(int ebnum) | |||
82 | 82 | ||
83 | err = mtd_erase(mtd, &ei); | 83 | err = mtd_erase(mtd, &ei); |
84 | if (err) { | 84 | if (err) { |
85 | printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); | 85 | pr_err("error %d while erasing EB %d\n", err, ebnum); |
86 | return err; | 86 | return err; |
87 | } | 87 | } |
88 | 88 | ||
89 | if (ei.state == MTD_ERASE_FAILED) { | 89 | if (ei.state == MTD_ERASE_FAILED) { |
90 | printk(PRINT_PREF "some erase error occurred at EB %d\n", | 90 | pr_err("some erase error occurred at EB %d\n", |
91 | ebnum); | 91 | ebnum); |
92 | return -EIO; | 92 | return -EIO; |
93 | } | 93 | } |
@@ -100,7 +100,7 @@ static int erase_whole_device(void) | |||
100 | int err; | 100 | int err; |
101 | unsigned int i; | 101 | unsigned int i; |
102 | 102 | ||
103 | printk(PRINT_PREF "erasing whole device\n"); | 103 | pr_info("erasing whole device\n"); |
104 | for (i = 0; i < ebcnt; ++i) { | 104 | for (i = 0; i < ebcnt; ++i) { |
105 | if (bbt[i]) | 105 | if (bbt[i]) |
106 | continue; | 106 | continue; |
@@ -109,7 +109,7 @@ static int erase_whole_device(void) | |||
109 | return err; | 109 | return err; |
110 | cond_resched(); | 110 | cond_resched(); |
111 | } | 111 | } |
112 | printk(PRINT_PREF "erased %u eraseblocks\n", i); | 112 | pr_info("erased %u eraseblocks\n", i); |
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
@@ -122,11 +122,11 @@ static int write_eraseblock(int ebnum) | |||
122 | set_random_data(writebuf, subpgsize); | 122 | set_random_data(writebuf, subpgsize); |
123 | err = mtd_write(mtd, addr, subpgsize, &written, writebuf); | 123 | err = mtd_write(mtd, addr, subpgsize, &written, writebuf); |
124 | if (unlikely(err || written != subpgsize)) { | 124 | if (unlikely(err || written != subpgsize)) { |
125 | printk(PRINT_PREF "error: write failed at %#llx\n", | 125 | pr_err("error: write failed at %#llx\n", |
126 | (long long)addr); | 126 | (long long)addr); |
127 | if (written != subpgsize) { | 127 | if (written != subpgsize) { |
128 | printk(PRINT_PREF " write size: %#x\n", subpgsize); | 128 | pr_err(" write size: %#x\n", subpgsize); |
129 | printk(PRINT_PREF " written: %#zx\n", written); | 129 | pr_err(" written: %#zx\n", written); |
130 | } | 130 | } |
131 | return err ? err : -1; | 131 | return err ? err : -1; |
132 | } | 132 | } |
@@ -136,11 +136,11 @@ static int write_eraseblock(int ebnum) | |||
136 | set_random_data(writebuf, subpgsize); | 136 | set_random_data(writebuf, subpgsize); |
137 | err = mtd_write(mtd, addr, subpgsize, &written, writebuf); | 137 | err = mtd_write(mtd, addr, subpgsize, &written, writebuf); |
138 | if (unlikely(err || written != subpgsize)) { | 138 | if (unlikely(err || written != subpgsize)) { |
139 | printk(PRINT_PREF "error: write failed at %#llx\n", | 139 | pr_err("error: write failed at %#llx\n", |
140 | (long long)addr); | 140 | (long long)addr); |
141 | if (written != subpgsize) { | 141 | if (written != subpgsize) { |
142 | printk(PRINT_PREF " write size: %#x\n", subpgsize); | 142 | pr_err(" write size: %#x\n", subpgsize); |
143 | printk(PRINT_PREF " written: %#zx\n", written); | 143 | pr_err(" written: %#zx\n", written); |
144 | } | 144 | } |
145 | return err ? err : -1; | 145 | return err ? err : -1; |
146 | } | 146 | } |
@@ -160,12 +160,12 @@ static int write_eraseblock2(int ebnum) | |||
160 | set_random_data(writebuf, subpgsize * k); | 160 | set_random_data(writebuf, subpgsize * k); |
161 | err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf); | 161 | err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf); |
162 | if (unlikely(err || written != subpgsize * k)) { | 162 | if (unlikely(err || written != subpgsize * k)) { |
163 | printk(PRINT_PREF "error: write failed at %#llx\n", | 163 | pr_err("error: write failed at %#llx\n", |
164 | (long long)addr); | 164 | (long long)addr); |
165 | if (written != subpgsize) { | 165 | if (written != subpgsize) { |
166 | printk(PRINT_PREF " write size: %#x\n", | 166 | pr_err(" write size: %#x\n", |
167 | subpgsize * k); | 167 | subpgsize * k); |
168 | printk(PRINT_PREF " written: %#08zx\n", | 168 | pr_err(" written: %#08zx\n", |
169 | written); | 169 | written); |
170 | } | 170 | } |
171 | return err ? err : -1; | 171 | return err ? err : -1; |
@@ -198,23 +198,23 @@ static int verify_eraseblock(int ebnum) | |||
198 | err = mtd_read(mtd, addr, subpgsize, &read, readbuf); | 198 | err = mtd_read(mtd, addr, subpgsize, &read, readbuf); |
199 | if (unlikely(err || read != subpgsize)) { | 199 | if (unlikely(err || read != subpgsize)) { |
200 | if (mtd_is_bitflip(err) && read == subpgsize) { | 200 | if (mtd_is_bitflip(err) && read == subpgsize) { |
201 | printk(PRINT_PREF "ECC correction at %#llx\n", | 201 | pr_info("ECC correction at %#llx\n", |
202 | (long long)addr); | 202 | (long long)addr); |
203 | err = 0; | 203 | err = 0; |
204 | } else { | 204 | } else { |
205 | printk(PRINT_PREF "error: read failed at %#llx\n", | 205 | pr_err("error: read failed at %#llx\n", |
206 | (long long)addr); | 206 | (long long)addr); |
207 | return err ? err : -1; | 207 | return err ? err : -1; |
208 | } | 208 | } |
209 | } | 209 | } |
210 | if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { | 210 | if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { |
211 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 211 | pr_err("error: verify failed at %#llx\n", |
212 | (long long)addr); | 212 | (long long)addr); |
213 | printk(PRINT_PREF "------------- written----------------\n"); | 213 | pr_info("------------- written----------------\n"); |
214 | print_subpage(writebuf); | 214 | print_subpage(writebuf); |
215 | printk(PRINT_PREF "------------- read ------------------\n"); | 215 | pr_info("------------- read ------------------\n"); |
216 | print_subpage(readbuf); | 216 | print_subpage(readbuf); |
217 | printk(PRINT_PREF "-------------------------------------\n"); | 217 | pr_info("-------------------------------------\n"); |
218 | errcnt += 1; | 218 | errcnt += 1; |
219 | } | 219 | } |
220 | 220 | ||
@@ -225,23 +225,23 @@ static int verify_eraseblock(int ebnum) | |||
225 | err = mtd_read(mtd, addr, subpgsize, &read, readbuf); | 225 | err = mtd_read(mtd, addr, subpgsize, &read, readbuf); |
226 | if (unlikely(err || read != subpgsize)) { | 226 | if (unlikely(err || read != subpgsize)) { |
227 | if (mtd_is_bitflip(err) && read == subpgsize) { | 227 | if (mtd_is_bitflip(err) && read == subpgsize) { |
228 | printk(PRINT_PREF "ECC correction at %#llx\n", | 228 | pr_info("ECC correction at %#llx\n", |
229 | (long long)addr); | 229 | (long long)addr); |
230 | err = 0; | 230 | err = 0; |
231 | } else { | 231 | } else { |
232 | printk(PRINT_PREF "error: read failed at %#llx\n", | 232 | pr_err("error: read failed at %#llx\n", |
233 | (long long)addr); | 233 | (long long)addr); |
234 | return err ? err : -1; | 234 | return err ? err : -1; |
235 | } | 235 | } |
236 | } | 236 | } |
237 | if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { | 237 | if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { |
238 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 238 | pr_info("error: verify failed at %#llx\n", |
239 | (long long)addr); | 239 | (long long)addr); |
240 | printk(PRINT_PREF "------------- written----------------\n"); | 240 | pr_info("------------- written----------------\n"); |
241 | print_subpage(writebuf); | 241 | print_subpage(writebuf); |
242 | printk(PRINT_PREF "------------- read ------------------\n"); | 242 | pr_info("------------- read ------------------\n"); |
243 | print_subpage(readbuf); | 243 | print_subpage(readbuf); |
244 | printk(PRINT_PREF "-------------------------------------\n"); | 244 | pr_info("-------------------------------------\n"); |
245 | errcnt += 1; | 245 | errcnt += 1; |
246 | } | 246 | } |
247 | 247 | ||
@@ -262,17 +262,17 @@ static int verify_eraseblock2(int ebnum) | |||
262 | err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf); | 262 | err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf); |
263 | if (unlikely(err || read != subpgsize * k)) { | 263 | if (unlikely(err || read != subpgsize * k)) { |
264 | if (mtd_is_bitflip(err) && read == subpgsize * k) { | 264 | if (mtd_is_bitflip(err) && read == subpgsize * k) { |
265 | printk(PRINT_PREF "ECC correction at %#llx\n", | 265 | pr_info("ECC correction at %#llx\n", |
266 | (long long)addr); | 266 | (long long)addr); |
267 | err = 0; | 267 | err = 0; |
268 | } else { | 268 | } else { |
269 | printk(PRINT_PREF "error: read failed at " | 269 | pr_err("error: read failed at " |
270 | "%#llx\n", (long long)addr); | 270 | "%#llx\n", (long long)addr); |
271 | return err ? err : -1; | 271 | return err ? err : -1; |
272 | } | 272 | } |
273 | } | 273 | } |
274 | if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) { | 274 | if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) { |
275 | printk(PRINT_PREF "error: verify failed at %#llx\n", | 275 | pr_err("error: verify failed at %#llx\n", |
276 | (long long)addr); | 276 | (long long)addr); |
277 | errcnt += 1; | 277 | errcnt += 1; |
278 | } | 278 | } |
@@ -295,17 +295,17 @@ static int verify_eraseblock_ff(int ebnum) | |||
295 | err = mtd_read(mtd, addr, subpgsize, &read, readbuf); | 295 | err = mtd_read(mtd, addr, subpgsize, &read, readbuf); |
296 | if (unlikely(err || read != subpgsize)) { | 296 | if (unlikely(err || read != subpgsize)) { |
297 | if (mtd_is_bitflip(err) && read == subpgsize) { | 297 | if (mtd_is_bitflip(err) && read == subpgsize) { |
298 | printk(PRINT_PREF "ECC correction at %#llx\n", | 298 | pr_info("ECC correction at %#llx\n", |
299 | (long long)addr); | 299 | (long long)addr); |
300 | err = 0; | 300 | err = 0; |
301 | } else { | 301 | } else { |
302 | printk(PRINT_PREF "error: read failed at " | 302 | pr_err("error: read failed at " |
303 | "%#llx\n", (long long)addr); | 303 | "%#llx\n", (long long)addr); |
304 | return err ? err : -1; | 304 | return err ? err : -1; |
305 | } | 305 | } |
306 | } | 306 | } |
307 | if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { | 307 | if (unlikely(memcmp(readbuf, writebuf, subpgsize))) { |
308 | printk(PRINT_PREF "error: verify 0xff failed at " | 308 | pr_err("error: verify 0xff failed at " |
309 | "%#llx\n", (long long)addr); | 309 | "%#llx\n", (long long)addr); |
310 | errcnt += 1; | 310 | errcnt += 1; |
311 | } | 311 | } |
@@ -320,7 +320,7 @@ static int verify_all_eraseblocks_ff(void) | |||
320 | int err; | 320 | int err; |
321 | unsigned int i; | 321 | unsigned int i; |
322 | 322 | ||
323 | printk(PRINT_PREF "verifying all eraseblocks for 0xff\n"); | 323 | pr_info("verifying all eraseblocks for 0xff\n"); |
324 | for (i = 0; i < ebcnt; ++i) { | 324 | for (i = 0; i < ebcnt; ++i) { |
325 | if (bbt[i]) | 325 | if (bbt[i]) |
326 | continue; | 326 | continue; |
@@ -328,10 +328,10 @@ static int verify_all_eraseblocks_ff(void) | |||
328 | if (err) | 328 | if (err) |
329 | return err; | 329 | return err; |
330 | if (i % 256 == 0) | 330 | if (i % 256 == 0) |
331 | printk(PRINT_PREF "verified up to eraseblock %u\n", i); | 331 | pr_info("verified up to eraseblock %u\n", i); |
332 | cond_resched(); | 332 | cond_resched(); |
333 | } | 333 | } |
334 | printk(PRINT_PREF "verified %u eraseblocks\n", i); | 334 | pr_info("verified %u eraseblocks\n", i); |
335 | return 0; | 335 | return 0; |
336 | } | 336 | } |
337 | 337 | ||
@@ -342,7 +342,7 @@ static int is_block_bad(int ebnum) | |||
342 | 342 | ||
343 | ret = mtd_block_isbad(mtd, addr); | 343 | ret = mtd_block_isbad(mtd, addr); |
344 | if (ret) | 344 | if (ret) |
345 | printk(PRINT_PREF "block %d is bad\n", ebnum); | 345 | pr_info("block %d is bad\n", ebnum); |
346 | return ret; | 346 | return ret; |
347 | } | 347 | } |
348 | 348 | ||
@@ -352,18 +352,18 @@ static int scan_for_bad_eraseblocks(void) | |||
352 | 352 | ||
353 | bbt = kzalloc(ebcnt, GFP_KERNEL); | 353 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
354 | if (!bbt) { | 354 | if (!bbt) { |
355 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 355 | pr_err("error: cannot allocate memory\n"); |
356 | return -ENOMEM; | 356 | return -ENOMEM; |
357 | } | 357 | } |
358 | 358 | ||
359 | printk(PRINT_PREF "scanning for bad eraseblocks\n"); | 359 | pr_info("scanning for bad eraseblocks\n"); |
360 | for (i = 0; i < ebcnt; ++i) { | 360 | for (i = 0; i < ebcnt; ++i) { |
361 | bbt[i] = is_block_bad(i) ? 1 : 0; | 361 | bbt[i] = is_block_bad(i) ? 1 : 0; |
362 | if (bbt[i]) | 362 | if (bbt[i]) |
363 | bad += 1; | 363 | bad += 1; |
364 | cond_resched(); | 364 | cond_resched(); |
365 | } | 365 | } |
366 | printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad); | 366 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); |
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
@@ -377,22 +377,22 @@ static int __init mtd_subpagetest_init(void) | |||
377 | printk(KERN_INFO "=================================================\n"); | 377 | printk(KERN_INFO "=================================================\n"); |
378 | 378 | ||
379 | if (dev < 0) { | 379 | if (dev < 0) { |
380 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | 380 | pr_info("Please specify a valid mtd-device via module parameter\n"); |
381 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | 381 | pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); |
382 | return -EINVAL; | 382 | return -EINVAL; |
383 | } | 383 | } |
384 | 384 | ||
385 | printk(PRINT_PREF "MTD device: %d\n", dev); | 385 | pr_info("MTD device: %d\n", dev); |
386 | 386 | ||
387 | mtd = get_mtd_device(NULL, dev); | 387 | mtd = get_mtd_device(NULL, dev); |
388 | if (IS_ERR(mtd)) { | 388 | if (IS_ERR(mtd)) { |
389 | err = PTR_ERR(mtd); | 389 | err = PTR_ERR(mtd); |
390 | printk(PRINT_PREF "error: cannot get MTD device\n"); | 390 | pr_err("error: cannot get MTD device\n"); |
391 | return err; | 391 | return err; |
392 | } | 392 | } |
393 | 393 | ||
394 | if (mtd->type != MTD_NANDFLASH) { | 394 | if (mtd->type != MTD_NANDFLASH) { |
395 | printk(PRINT_PREF "this test requires NAND flash\n"); | 395 | pr_info("this test requires NAND flash\n"); |
396 | goto out; | 396 | goto out; |
397 | } | 397 | } |
398 | 398 | ||
@@ -402,7 +402,7 @@ static int __init mtd_subpagetest_init(void) | |||
402 | ebcnt = tmp; | 402 | ebcnt = tmp; |
403 | pgcnt = mtd->erasesize / mtd->writesize; | 403 | pgcnt = mtd->erasesize / mtd->writesize; |
404 | 404 | ||
405 | printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, " | 405 | pr_info("MTD device size %llu, eraseblock size %u, " |
406 | "page size %u, subpage size %u, count of eraseblocks %u, " | 406 | "page size %u, subpage size %u, count of eraseblocks %u, " |
407 | "pages per eraseblock %u, OOB size %u\n", | 407 | "pages per eraseblock %u, OOB size %u\n", |
408 | (unsigned long long)mtd->size, mtd->erasesize, | 408 | (unsigned long long)mtd->size, mtd->erasesize, |
@@ -412,12 +412,12 @@ static int __init mtd_subpagetest_init(void) | |||
412 | bufsize = subpgsize * 32; | 412 | bufsize = subpgsize * 32; |
413 | writebuf = kmalloc(bufsize, GFP_KERNEL); | 413 | writebuf = kmalloc(bufsize, GFP_KERNEL); |
414 | if (!writebuf) { | 414 | if (!writebuf) { |
415 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 415 | pr_info("error: cannot allocate memory\n"); |
416 | goto out; | 416 | goto out; |
417 | } | 417 | } |
418 | readbuf = kmalloc(bufsize, GFP_KERNEL); | 418 | readbuf = kmalloc(bufsize, GFP_KERNEL); |
419 | if (!readbuf) { | 419 | if (!readbuf) { |
420 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 420 | pr_info("error: cannot allocate memory\n"); |
421 | goto out; | 421 | goto out; |
422 | } | 422 | } |
423 | 423 | ||
@@ -429,7 +429,7 @@ static int __init mtd_subpagetest_init(void) | |||
429 | if (err) | 429 | if (err) |
430 | goto out; | 430 | goto out; |
431 | 431 | ||
432 | printk(PRINT_PREF "writing whole device\n"); | 432 | pr_info("writing whole device\n"); |
433 | simple_srand(1); | 433 | simple_srand(1); |
434 | for (i = 0; i < ebcnt; ++i) { | 434 | for (i = 0; i < ebcnt; ++i) { |
435 | if (bbt[i]) | 435 | if (bbt[i]) |
@@ -438,13 +438,13 @@ static int __init mtd_subpagetest_init(void) | |||
438 | if (unlikely(err)) | 438 | if (unlikely(err)) |
439 | goto out; | 439 | goto out; |
440 | if (i % 256 == 0) | 440 | if (i % 256 == 0) |
441 | printk(PRINT_PREF "written up to eraseblock %u\n", i); | 441 | pr_info("written up to eraseblock %u\n", i); |
442 | cond_resched(); | 442 | cond_resched(); |
443 | } | 443 | } |
444 | printk(PRINT_PREF "written %u eraseblocks\n", i); | 444 | pr_info("written %u eraseblocks\n", i); |
445 | 445 | ||
446 | simple_srand(1); | 446 | simple_srand(1); |
447 | printk(PRINT_PREF "verifying all eraseblocks\n"); | 447 | pr_info("verifying all eraseblocks\n"); |
448 | for (i = 0; i < ebcnt; ++i) { | 448 | for (i = 0; i < ebcnt; ++i) { |
449 | if (bbt[i]) | 449 | if (bbt[i]) |
450 | continue; | 450 | continue; |
@@ -452,10 +452,10 @@ static int __init mtd_subpagetest_init(void) | |||
452 | if (unlikely(err)) | 452 | if (unlikely(err)) |
453 | goto out; | 453 | goto out; |
454 | if (i % 256 == 0) | 454 | if (i % 256 == 0) |
455 | printk(PRINT_PREF "verified up to eraseblock %u\n", i); | 455 | pr_info("verified up to eraseblock %u\n", i); |
456 | cond_resched(); | 456 | cond_resched(); |
457 | } | 457 | } |
458 | printk(PRINT_PREF "verified %u eraseblocks\n", i); | 458 | pr_info("verified %u eraseblocks\n", i); |
459 | 459 | ||
460 | err = erase_whole_device(); | 460 | err = erase_whole_device(); |
461 | if (err) | 461 | if (err) |
@@ -467,7 +467,7 @@ static int __init mtd_subpagetest_init(void) | |||
467 | 467 | ||
468 | /* Write all eraseblocks */ | 468 | /* Write all eraseblocks */ |
469 | simple_srand(3); | 469 | simple_srand(3); |
470 | printk(PRINT_PREF "writing whole device\n"); | 470 | pr_info("writing whole device\n"); |
471 | for (i = 0; i < ebcnt; ++i) { | 471 | for (i = 0; i < ebcnt; ++i) { |
472 | if (bbt[i]) | 472 | if (bbt[i]) |
473 | continue; | 473 | continue; |
@@ -475,14 +475,14 @@ static int __init mtd_subpagetest_init(void) | |||
475 | if (unlikely(err)) | 475 | if (unlikely(err)) |
476 | goto out; | 476 | goto out; |
477 | if (i % 256 == 0) | 477 | if (i % 256 == 0) |
478 | printk(PRINT_PREF "written up to eraseblock %u\n", i); | 478 | pr_info("written up to eraseblock %u\n", i); |
479 | cond_resched(); | 479 | cond_resched(); |
480 | } | 480 | } |
481 | printk(PRINT_PREF "written %u eraseblocks\n", i); | 481 | pr_info("written %u eraseblocks\n", i); |
482 | 482 | ||
483 | /* Check all eraseblocks */ | 483 | /* Check all eraseblocks */ |
484 | simple_srand(3); | 484 | simple_srand(3); |
485 | printk(PRINT_PREF "verifying all eraseblocks\n"); | 485 | pr_info("verifying all eraseblocks\n"); |
486 | for (i = 0; i < ebcnt; ++i) { | 486 | for (i = 0; i < ebcnt; ++i) { |
487 | if (bbt[i]) | 487 | if (bbt[i]) |
488 | continue; | 488 | continue; |
@@ -490,10 +490,10 @@ static int __init mtd_subpagetest_init(void) | |||
490 | if (unlikely(err)) | 490 | if (unlikely(err)) |
491 | goto out; | 491 | goto out; |
492 | if (i % 256 == 0) | 492 | if (i % 256 == 0) |
493 | printk(PRINT_PREF "verified up to eraseblock %u\n", i); | 493 | pr_info("verified up to eraseblock %u\n", i); |
494 | cond_resched(); | 494 | cond_resched(); |
495 | } | 495 | } |
496 | printk(PRINT_PREF "verified %u eraseblocks\n", i); | 496 | pr_info("verified %u eraseblocks\n", i); |
497 | 497 | ||
498 | err = erase_whole_device(); | 498 | err = erase_whole_device(); |
499 | if (err) | 499 | if (err) |
@@ -503,7 +503,7 @@ static int __init mtd_subpagetest_init(void) | |||
503 | if (err) | 503 | if (err) |
504 | goto out; | 504 | goto out; |
505 | 505 | ||
506 | printk(PRINT_PREF "finished with %d errors\n", errcnt); | 506 | pr_info("finished with %d errors\n", errcnt); |
507 | 507 | ||
508 | out: | 508 | out: |
509 | kfree(bbt); | 509 | kfree(bbt); |
@@ -511,7 +511,7 @@ out: | |||
511 | kfree(writebuf); | 511 | kfree(writebuf); |
512 | put_mtd_device(mtd); | 512 | put_mtd_device(mtd); |
513 | if (err) | 513 | if (err) |
514 | printk(PRINT_PREF "error %d occurred\n", err); | 514 | pr_info("error %d occurred\n", err); |
515 | printk(KERN_INFO "=================================================\n"); | 515 | printk(KERN_INFO "=================================================\n"); |
516 | return err; | 516 | return err; |
517 | } | 517 | } |
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c index b65861bc7b8e..c4cde1e9eddb 100644 --- a/drivers/mtd/tests/mtd_torturetest.c +++ b/drivers/mtd/tests/mtd_torturetest.c | |||
@@ -23,6 +23,8 @@ | |||
23 | * damage caused by this program. | 23 | * damage caused by this program. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
27 | |||
26 | #include <linux/init.h> | 28 | #include <linux/init.h> |
27 | #include <linux/module.h> | 29 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
@@ -31,7 +33,6 @@ | |||
31 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
32 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
33 | 35 | ||
34 | #define PRINT_PREF KERN_INFO "mtd_torturetest: " | ||
35 | #define RETRIES 3 | 36 | #define RETRIES 3 |
36 | 37 | ||
37 | static int eb = 8; | 38 | static int eb = 8; |
@@ -107,12 +108,12 @@ static inline int erase_eraseblock(int ebnum) | |||
107 | 108 | ||
108 | err = mtd_erase(mtd, &ei); | 109 | err = mtd_erase(mtd, &ei); |
109 | if (err) { | 110 | if (err) { |
110 | printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); | 111 | pr_err("error %d while erasing EB %d\n", err, ebnum); |
111 | return err; | 112 | return err; |
112 | } | 113 | } |
113 | 114 | ||
114 | if (ei.state == MTD_ERASE_FAILED) { | 115 | if (ei.state == MTD_ERASE_FAILED) { |
115 | printk(PRINT_PREF "some erase error occurred at EB %d\n", | 116 | pr_err("some erase error occurred at EB %d\n", |
116 | ebnum); | 117 | ebnum); |
117 | return -EIO; | 118 | return -EIO; |
118 | } | 119 | } |
@@ -139,40 +140,40 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf) | |||
139 | retry: | 140 | retry: |
140 | err = mtd_read(mtd, addr, len, &read, check_buf); | 141 | err = mtd_read(mtd, addr, len, &read, check_buf); |
141 | if (mtd_is_bitflip(err)) | 142 | if (mtd_is_bitflip(err)) |
142 | printk(PRINT_PREF "single bit flip occurred at EB %d " | 143 | pr_err("single bit flip occurred at EB %d " |
143 | "MTD reported that it was fixed.\n", ebnum); | 144 | "MTD reported that it was fixed.\n", ebnum); |
144 | else if (err) { | 145 | else if (err) { |
145 | printk(PRINT_PREF "error %d while reading EB %d, " | 146 | pr_err("error %d while reading EB %d, " |
146 | "read %zd\n", err, ebnum, read); | 147 | "read %zd\n", err, ebnum, read); |
147 | return err; | 148 | return err; |
148 | } | 149 | } |
149 | 150 | ||
150 | if (read != len) { | 151 | if (read != len) { |
151 | printk(PRINT_PREF "failed to read %zd bytes from EB %d, " | 152 | pr_err("failed to read %zd bytes from EB %d, " |
152 | "read only %zd, but no error reported\n", | 153 | "read only %zd, but no error reported\n", |
153 | len, ebnum, read); | 154 | len, ebnum, read); |
154 | return -EIO; | 155 | return -EIO; |
155 | } | 156 | } |
156 | 157 | ||
157 | if (memcmp(buf, check_buf, len)) { | 158 | if (memcmp(buf, check_buf, len)) { |
158 | printk(PRINT_PREF "read wrong data from EB %d\n", ebnum); | 159 | pr_err("read wrong data from EB %d\n", ebnum); |
159 | report_corrupt(check_buf, buf); | 160 | report_corrupt(check_buf, buf); |
160 | 161 | ||
161 | if (retries++ < RETRIES) { | 162 | if (retries++ < RETRIES) { |
162 | /* Try read again */ | 163 | /* Try read again */ |
163 | yield(); | 164 | yield(); |
164 | printk(PRINT_PREF "re-try reading data from EB %d\n", | 165 | pr_info("re-try reading data from EB %d\n", |
165 | ebnum); | 166 | ebnum); |
166 | goto retry; | 167 | goto retry; |
167 | } else { | 168 | } else { |
168 | printk(PRINT_PREF "retried %d times, still errors, " | 169 | pr_info("retried %d times, still errors, " |
169 | "give-up\n", RETRIES); | 170 | "give-up\n", RETRIES); |
170 | return -EINVAL; | 171 | return -EINVAL; |
171 | } | 172 | } |
172 | } | 173 | } |
173 | 174 | ||
174 | if (retries != 0) | 175 | if (retries != 0) |
175 | printk(PRINT_PREF "only attempt number %d was OK (!!!)\n", | 176 | pr_info("only attempt number %d was OK (!!!)\n", |
176 | retries); | 177 | retries); |
177 | 178 | ||
178 | return 0; | 179 | return 0; |
@@ -191,12 +192,12 @@ static inline int write_pattern(int ebnum, void *buf) | |||
191 | } | 192 | } |
192 | err = mtd_write(mtd, addr, len, &written, buf); | 193 | err = mtd_write(mtd, addr, len, &written, buf); |
193 | if (err) { | 194 | if (err) { |
194 | printk(PRINT_PREF "error %d while writing EB %d, written %zd" | 195 | pr_err("error %d while writing EB %d, written %zd" |
195 | " bytes\n", err, ebnum, written); | 196 | " bytes\n", err, ebnum, written); |
196 | return err; | 197 | return err; |
197 | } | 198 | } |
198 | if (written != len) { | 199 | if (written != len) { |
199 | printk(PRINT_PREF "written only %zd bytes of %zd, but no error" | 200 | pr_info("written only %zd bytes of %zd, but no error" |
200 | " reported\n", written, len); | 201 | " reported\n", written, len); |
201 | return -EIO; | 202 | return -EIO; |
202 | } | 203 | } |
@@ -211,64 +212,64 @@ static int __init tort_init(void) | |||
211 | 212 | ||
212 | printk(KERN_INFO "\n"); | 213 | printk(KERN_INFO "\n"); |
213 | printk(KERN_INFO "=================================================\n"); | 214 | printk(KERN_INFO "=================================================\n"); |
214 | printk(PRINT_PREF "Warning: this program is trying to wear out your " | 215 | pr_info("Warning: this program is trying to wear out your " |
215 | "flash, stop it if this is not wanted.\n"); | 216 | "flash, stop it if this is not wanted.\n"); |
216 | 217 | ||
217 | if (dev < 0) { | 218 | if (dev < 0) { |
218 | printk(PRINT_PREF "Please specify a valid mtd-device via module paramter\n"); | 219 | pr_info("Please specify a valid mtd-device via module parameter\n"); |
219 | printk(KERN_CRIT "CAREFUL: This test wipes all data on the specified MTD device!\n"); | 220 | pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); |
220 | return -EINVAL; | 221 | return -EINVAL; |
221 | } | 222 | } |
222 | 223 | ||
223 | printk(PRINT_PREF "MTD device: %d\n", dev); | 224 | pr_info("MTD device: %d\n", dev); |
224 | printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n", | 225 | pr_info("torture %d eraseblocks (%d-%d) of mtd%d\n", |
225 | ebcnt, eb, eb + ebcnt - 1, dev); | 226 | ebcnt, eb, eb + ebcnt - 1, dev); |
226 | if (pgcnt) | 227 | if (pgcnt) |
227 | printk(PRINT_PREF "torturing just %d pages per eraseblock\n", | 228 | pr_info("torturing just %d pages per eraseblock\n", |
228 | pgcnt); | 229 | pgcnt); |
229 | printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled"); | 230 | pr_info("write verify %s\n", check ? "enabled" : "disabled"); |
230 | 231 | ||
231 | mtd = get_mtd_device(NULL, dev); | 232 | mtd = get_mtd_device(NULL, dev); |
232 | if (IS_ERR(mtd)) { | 233 | if (IS_ERR(mtd)) { |
233 | err = PTR_ERR(mtd); | 234 | err = PTR_ERR(mtd); |
234 | printk(PRINT_PREF "error: cannot get MTD device\n"); | 235 | pr_err("error: cannot get MTD device\n"); |
235 | return err; | 236 | return err; |
236 | } | 237 | } |
237 | 238 | ||
238 | if (mtd->writesize == 1) { | 239 | if (mtd->writesize == 1) { |
239 | printk(PRINT_PREF "not NAND flash, assume page size is 512 " | 240 | pr_info("not NAND flash, assume page size is 512 " |
240 | "bytes.\n"); | 241 | "bytes.\n"); |
241 | pgsize = 512; | 242 | pgsize = 512; |
242 | } else | 243 | } else |
243 | pgsize = mtd->writesize; | 244 | pgsize = mtd->writesize; |
244 | 245 | ||
245 | if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { | 246 | if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { |
246 | printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt); | 247 | pr_err("error: invalid pgcnt value %d\n", pgcnt); |
247 | goto out_mtd; | 248 | goto out_mtd; |
248 | } | 249 | } |
249 | 250 | ||
250 | err = -ENOMEM; | 251 | err = -ENOMEM; |
251 | patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); | 252 | patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); |
252 | if (!patt_5A5) { | 253 | if (!patt_5A5) { |
253 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 254 | pr_err("error: cannot allocate memory\n"); |
254 | goto out_mtd; | 255 | goto out_mtd; |
255 | } | 256 | } |
256 | 257 | ||
257 | patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); | 258 | patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); |
258 | if (!patt_A5A) { | 259 | if (!patt_A5A) { |
259 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 260 | pr_err("error: cannot allocate memory\n"); |
260 | goto out_patt_5A5; | 261 | goto out_patt_5A5; |
261 | } | 262 | } |
262 | 263 | ||
263 | patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); | 264 | patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); |
264 | if (!patt_FF) { | 265 | if (!patt_FF) { |
265 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 266 | pr_err("error: cannot allocate memory\n"); |
266 | goto out_patt_A5A; | 267 | goto out_patt_A5A; |
267 | } | 268 | } |
268 | 269 | ||
269 | check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); | 270 | check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); |
270 | if (!check_buf) { | 271 | if (!check_buf) { |
271 | printk(PRINT_PREF "error: cannot allocate memory\n"); | 272 | pr_err("error: cannot allocate memory\n"); |
272 | goto out_patt_FF; | 273 | goto out_patt_FF; |
273 | } | 274 | } |
274 | 275 | ||
@@ -295,13 +296,13 @@ static int __init tort_init(void) | |||
295 | err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize); | 296 | err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize); |
296 | 297 | ||
297 | if (err < 0) { | 298 | if (err < 0) { |
298 | printk(PRINT_PREF "block_isbad() returned %d " | 299 | pr_info("block_isbad() returned %d " |
299 | "for EB %d\n", err, i); | 300 | "for EB %d\n", err, i); |
300 | goto out; | 301 | goto out; |
301 | } | 302 | } |
302 | 303 | ||
303 | if (err) { | 304 | if (err) { |
304 | printk("EB %d is bad. Skip it.\n", i); | 305 | pr_err("EB %d is bad. Skip it.\n", i); |
305 | bad_ebs[i - eb] = 1; | 306 | bad_ebs[i - eb] = 1; |
306 | } | 307 | } |
307 | } | 308 | } |
@@ -329,7 +330,7 @@ static int __init tort_init(void) | |||
329 | continue; | 330 | continue; |
330 | err = check_eraseblock(i, patt_FF); | 331 | err = check_eraseblock(i, patt_FF); |
331 | if (err) { | 332 | if (err) { |
332 | printk(PRINT_PREF "verify failed" | 333 | pr_info("verify failed" |
333 | " for 0xFF... pattern\n"); | 334 | " for 0xFF... pattern\n"); |
334 | goto out; | 335 | goto out; |
335 | } | 336 | } |
@@ -362,7 +363,7 @@ static int __init tort_init(void) | |||
362 | patt = patt_A5A; | 363 | patt = patt_A5A; |
363 | err = check_eraseblock(i, patt); | 364 | err = check_eraseblock(i, patt); |
364 | if (err) { | 365 | if (err) { |
365 | printk(PRINT_PREF "verify failed for %s" | 366 | pr_info("verify failed for %s" |
366 | " pattern\n", | 367 | " pattern\n", |
367 | ((eb + erase_cycles) & 1) ? | 368 | ((eb + erase_cycles) & 1) ? |
368 | "0x55AA55..." : "0xAA55AA..."); | 369 | "0x55AA55..." : "0xAA55AA..."); |
@@ -380,7 +381,7 @@ static int __init tort_init(void) | |||
380 | stop_timing(); | 381 | stop_timing(); |
381 | ms = (finish.tv_sec - start.tv_sec) * 1000 + | 382 | ms = (finish.tv_sec - start.tv_sec) * 1000 + |
382 | (finish.tv_usec - start.tv_usec) / 1000; | 383 | (finish.tv_usec - start.tv_usec) / 1000; |
383 | printk(PRINT_PREF "%08u erase cycles done, took %lu " | 384 | pr_info("%08u erase cycles done, took %lu " |
384 | "milliseconds (%lu seconds)\n", | 385 | "milliseconds (%lu seconds)\n", |
385 | erase_cycles, ms, ms / 1000); | 386 | erase_cycles, ms, ms / 1000); |
386 | start_timing(); | 387 | start_timing(); |
@@ -391,7 +392,7 @@ static int __init tort_init(void) | |||
391 | } | 392 | } |
392 | out: | 393 | out: |
393 | 394 | ||
394 | printk(PRINT_PREF "finished after %u erase cycles\n", | 395 | pr_info("finished after %u erase cycles\n", |
395 | erase_cycles); | 396 | erase_cycles); |
396 | kfree(check_buf); | 397 | kfree(check_buf); |
397 | out_patt_FF: | 398 | out_patt_FF: |
@@ -403,7 +404,7 @@ out_patt_5A5: | |||
403 | out_mtd: | 404 | out_mtd: |
404 | put_mtd_device(mtd); | 405 | put_mtd_device(mtd); |
405 | if (err) | 406 | if (err) |
406 | printk(PRINT_PREF "error %d occurred during torturing\n", err); | 407 | pr_info("error %d occurred during torturing\n", err); |
407 | printk(KERN_INFO "=================================================\n"); | 408 | printk(KERN_INFO "=================================================\n"); |
408 | return err; | 409 | return err; |
409 | } | 410 | } |
@@ -441,9 +442,9 @@ static void report_corrupt(unsigned char *read, unsigned char *written) | |||
441 | &bits) >= 0) | 442 | &bits) >= 0) |
442 | pages++; | 443 | pages++; |
443 | 444 | ||
444 | printk(PRINT_PREF "verify fails on %d pages, %d bytes/%d bits\n", | 445 | pr_info("verify fails on %d pages, %d bytes/%d bits\n", |
445 | pages, bytes, bits); | 446 | pages, bytes, bits); |
446 | printk(PRINT_PREF "The following is a list of all differences between" | 447 | pr_info("The following is a list of all differences between" |
447 | " what was read from flash and what was expected\n"); | 448 | " what was read from flash and what was expected\n"); |
448 | 449 | ||
449 | for (i = 0; i < check_len; i += pgsize) { | 450 | for (i = 0; i < check_len; i += pgsize) { |
@@ -457,7 +458,7 @@ static void report_corrupt(unsigned char *read, unsigned char *written) | |||
457 | printk("-------------------------------------------------------" | 458 | printk("-------------------------------------------------------" |
458 | "----------------------------------\n"); | 459 | "----------------------------------\n"); |
459 | 460 | ||
460 | printk(PRINT_PREF "Page %zd has %d bytes/%d bits failing verify," | 461 | pr_info("Page %zd has %d bytes/%d bits failing verify," |
461 | " starting at offset 0x%x\n", | 462 | " starting at offset 0x%x\n", |
462 | (mtd->erasesize - check_len + i) / pgsize, | 463 | (mtd->erasesize - check_len + i) / pgsize, |
463 | bytes, bits, first); | 464 | bytes, bits, first); |
diff --git a/drivers/of/base.c b/drivers/of/base.c index db8d211a0d05..2390ddb22d60 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -629,7 +629,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, | |||
629 | read_unlock(&devtree_lock); | 629 | read_unlock(&devtree_lock); |
630 | return np; | 630 | return np; |
631 | } | 631 | } |
632 | EXPORT_SYMBOL(of_find_matching_node); | 632 | EXPORT_SYMBOL(of_find_matching_node_and_match); |
633 | 633 | ||
634 | /** | 634 | /** |
635 | * of_modalias_node - Lookup appropriate modalias for a device node | 635 | * of_modalias_node - Lookup appropriate modalias for a device node |
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index adb3a4b59cb3..6ba047f5ac2c 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c | |||
@@ -239,44 +239,37 @@ static bool is_full_charged(struct charger_manager *cm) | |||
239 | int uV; | 239 | int uV; |
240 | 240 | ||
241 | /* If there is no battery, it cannot be charged */ | 241 | /* If there is no battery, it cannot be charged */ |
242 | if (!is_batt_present(cm)) { | 242 | if (!is_batt_present(cm)) |
243 | val.intval = 0; | 243 | return false; |
244 | goto out; | ||
245 | } | ||
246 | 244 | ||
247 | if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) { | 245 | if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) { |
246 | val.intval = 0; | ||
247 | |||
248 | /* Not full if capacity of fuel gauge isn't full */ | 248 | /* Not full if capacity of fuel gauge isn't full */ |
249 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | 249 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, |
250 | POWER_SUPPLY_PROP_CHARGE_FULL, &val); | 250 | POWER_SUPPLY_PROP_CHARGE_FULL, &val); |
251 | if (!ret && val.intval > desc->fullbatt_full_capacity) { | 251 | if (!ret && val.intval > desc->fullbatt_full_capacity) |
252 | val.intval = 1; | 252 | return true; |
253 | goto out; | ||
254 | } | ||
255 | } | 253 | } |
256 | 254 | ||
257 | /* Full, if it's over the fullbatt voltage */ | 255 | /* Full, if it's over the fullbatt voltage */ |
258 | if (desc->fullbatt_uV > 0) { | 256 | if (desc->fullbatt_uV > 0) { |
259 | ret = get_batt_uV(cm, &uV); | 257 | ret = get_batt_uV(cm, &uV); |
260 | if (!ret && uV >= desc->fullbatt_uV) { | 258 | if (!ret && uV >= desc->fullbatt_uV) |
261 | val.intval = 1; | 259 | return true; |
262 | goto out; | ||
263 | } | ||
264 | } | 260 | } |
265 | 261 | ||
266 | /* Full, if the capacity is more than fullbatt_soc */ | 262 | /* Full, if the capacity is more than fullbatt_soc */ |
267 | if (cm->fuel_gauge && desc->fullbatt_soc > 0) { | 263 | if (cm->fuel_gauge && desc->fullbatt_soc > 0) { |
264 | val.intval = 0; | ||
265 | |||
268 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, | 266 | ret = cm->fuel_gauge->get_property(cm->fuel_gauge, |
269 | POWER_SUPPLY_PROP_CAPACITY, &val); | 267 | POWER_SUPPLY_PROP_CAPACITY, &val); |
270 | if (!ret && val.intval >= desc->fullbatt_soc) { | 268 | if (!ret && val.intval >= desc->fullbatt_soc) |
271 | val.intval = 1; | 269 | return true; |
272 | goto out; | ||
273 | } | ||
274 | } | 270 | } |
275 | 271 | ||
276 | val.intval = 0; | 272 | return false; |
277 | |||
278 | out: | ||
279 | return val.intval ? true : false; | ||
280 | } | 273 | } |
281 | 274 | ||
282 | /** | 275 | /** |
@@ -489,8 +482,9 @@ static void fullbatt_vchk(struct work_struct *work) | |||
489 | return; | 482 | return; |
490 | } | 483 | } |
491 | 484 | ||
492 | diff = desc->fullbatt_uV; | 485 | diff = desc->fullbatt_uV - batt_uV; |
493 | diff -= batt_uV; | 486 | if (diff < 0) |
487 | return; | ||
494 | 488 | ||
495 | dev_info(cm->dev, "VBATT dropped %duV after full-batt.\n", diff); | 489 | dev_info(cm->dev, "VBATT dropped %duV after full-batt.\n", diff); |
496 | 490 | ||
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index ed81720e7b2b..e513cd998170 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig | |||
@@ -112,6 +112,17 @@ config PWM_SAMSUNG | |||
112 | To compile this driver as a module, choose M here: the module | 112 | To compile this driver as a module, choose M here: the module |
113 | will be called pwm-samsung. | 113 | will be called pwm-samsung. |
114 | 114 | ||
115 | config PWM_SPEAR | ||
116 | tristate "STMicroelectronics SPEAr PWM support" | ||
117 | depends on PLAT_SPEAR | ||
118 | depends on OF | ||
119 | help | ||
120 | Generic PWM framework driver for the PWM controller on ST | ||
121 | SPEAr SoCs. | ||
122 | |||
123 | To compile this driver as a module, choose M here: the module | ||
124 | will be called pwm-spear. | ||
125 | |||
115 | config PWM_TEGRA | 126 | config PWM_TEGRA |
116 | tristate "NVIDIA Tegra PWM support" | 127 | tristate "NVIDIA Tegra PWM support" |
117 | depends on ARCH_TEGRA | 128 | depends on ARCH_TEGRA |
@@ -125,6 +136,7 @@ config PWM_TEGRA | |||
125 | config PWM_TIECAP | 136 | config PWM_TIECAP |
126 | tristate "ECAP PWM support" | 137 | tristate "ECAP PWM support" |
127 | depends on SOC_AM33XX | 138 | depends on SOC_AM33XX |
139 | select PWM_TIPWMSS | ||
128 | help | 140 | help |
129 | PWM driver support for the ECAP APWM controller found on AM33XX | 141 | PWM driver support for the ECAP APWM controller found on AM33XX |
130 | TI SOC | 142 | TI SOC |
@@ -135,6 +147,7 @@ config PWM_TIECAP | |||
135 | config PWM_TIEHRPWM | 147 | config PWM_TIEHRPWM |
136 | tristate "EHRPWM PWM support" | 148 | tristate "EHRPWM PWM support" |
137 | depends on SOC_AM33XX | 149 | depends on SOC_AM33XX |
150 | select PWM_TIPWMSS | ||
138 | help | 151 | help |
139 | PWM driver support for the EHRPWM controller found on AM33XX | 152 | PWM driver support for the EHRPWM controller found on AM33XX |
140 | TI SOC | 153 | TI SOC |
@@ -142,14 +155,32 @@ config PWM_TIEHRPWM | |||
142 | To compile this driver as a module, choose M here: the module | 155 | To compile this driver as a module, choose M here: the module |
143 | will be called pwm-tiehrpwm. | 156 | will be called pwm-tiehrpwm. |
144 | 157 | ||
145 | config PWM_TWL6030 | 158 | config PWM_TIPWMSS |
146 | tristate "TWL6030 PWM support" | 159 | bool |
160 | depends on SOC_AM33XX && (PWM_TIEHRPWM || PWM_TIECAP) | ||
161 | help | ||
162 | PWM Subsystem driver support for AM33xx SOC. | ||
163 | |||
164 | PWM submodules require PWM config space access from submodule | ||
165 | drivers and require common parent driver support. | ||
166 | |||
167 | config PWM_TWL | ||
168 | tristate "TWL4030/6030 PWM support" | ||
169 | depends on TWL4030_CORE | ||
170 | help | ||
171 | Generic PWM framework driver for TWL4030/6030. | ||
172 | |||
173 | To compile this driver as a module, choose M here: the module | ||
174 | will be called pwm-twl. | ||
175 | |||
176 | config PWM_TWL_LED | ||
177 | tristate "TWL4030/6030 PWM support for LED drivers" | ||
147 | depends on TWL4030_CORE | 178 | depends on TWL4030_CORE |
148 | help | 179 | help |
149 | Generic PWM framework driver for TWL6030. | 180 | Generic PWM framework driver for TWL4030/6030 LED terminals. |
150 | 181 | ||
151 | To compile this driver as a module, choose M here: the module | 182 | To compile this driver as a module, choose M here: the module |
152 | will be called pwm-twl6030. | 183 | will be called pwm-twl-led. |
153 | 184 | ||
154 | config PWM_VT8500 | 185 | config PWM_VT8500 |
155 | tristate "vt8500 pwm support" | 186 | tristate "vt8500 pwm support" |
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index acfe4821c58b..62a2963cfe58 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile | |||
@@ -8,8 +8,11 @@ obj-$(CONFIG_PWM_MXS) += pwm-mxs.o | |||
8 | obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o | 8 | obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o |
9 | obj-$(CONFIG_PWM_PXA) += pwm-pxa.o | 9 | obj-$(CONFIG_PWM_PXA) += pwm-pxa.o |
10 | obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o | 10 | obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o |
11 | obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o | ||
11 | obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o | 12 | obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o |
12 | obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o | 13 | obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o |
13 | obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o | 14 | obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o |
14 | obj-$(CONFIG_PWM_TWL6030) += pwm-twl6030.o | 15 | obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o |
16 | obj-$(CONFIG_PWM_TWL) += pwm-twl.o | ||
17 | obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o | ||
15 | obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o | 18 | obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o |
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index f5acdaa52707..903138b18842 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c | |||
@@ -32,6 +32,9 @@ | |||
32 | 32 | ||
33 | #define MAX_PWMS 1024 | 33 | #define MAX_PWMS 1024 |
34 | 34 | ||
35 | /* flags in the third cell of the DT PWM specifier */ | ||
36 | #define PWM_SPEC_POLARITY (1 << 0) | ||
37 | |||
35 | static DEFINE_MUTEX(pwm_lookup_lock); | 38 | static DEFINE_MUTEX(pwm_lookup_lock); |
36 | static LIST_HEAD(pwm_lookup_list); | 39 | static LIST_HEAD(pwm_lookup_list); |
37 | static DEFINE_MUTEX(pwm_lock); | 40 | static DEFINE_MUTEX(pwm_lock); |
@@ -129,6 +132,32 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label) | |||
129 | return 0; | 132 | return 0; |
130 | } | 133 | } |
131 | 134 | ||
135 | struct pwm_device * | ||
136 | of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args) | ||
137 | { | ||
138 | struct pwm_device *pwm; | ||
139 | |||
140 | if (pc->of_pwm_n_cells < 3) | ||
141 | return ERR_PTR(-EINVAL); | ||
142 | |||
143 | if (args->args[0] >= pc->npwm) | ||
144 | return ERR_PTR(-EINVAL); | ||
145 | |||
146 | pwm = pwm_request_from_chip(pc, args->args[0], NULL); | ||
147 | if (IS_ERR(pwm)) | ||
148 | return pwm; | ||
149 | |||
150 | pwm_set_period(pwm, args->args[1]); | ||
151 | |||
152 | if (args->args[2] & PWM_SPEC_POLARITY) | ||
153 | pwm_set_polarity(pwm, PWM_POLARITY_INVERSED); | ||
154 | else | ||
155 | pwm_set_polarity(pwm, PWM_POLARITY_NORMAL); | ||
156 | |||
157 | return pwm; | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags); | ||
160 | |||
132 | static struct pwm_device * | 161 | static struct pwm_device * |
133 | of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) | 162 | of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args) |
134 | { | 163 | { |
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c index 8f26e9fcea97..65a86bdeabed 100644 --- a/drivers/pwm/pwm-imx.c +++ b/drivers/pwm/pwm-imx.c | |||
@@ -235,7 +235,7 @@ static int imx_pwm_probe(struct platform_device *pdev) | |||
235 | { | 235 | { |
236 | const struct of_device_id *of_id = | 236 | const struct of_device_id *of_id = |
237 | of_match_device(imx_pwm_dt_ids, &pdev->dev); | 237 | of_match_device(imx_pwm_dt_ids, &pdev->dev); |
238 | struct imx_pwm_data *data; | 238 | const struct imx_pwm_data *data; |
239 | struct imx_chip *imx; | 239 | struct imx_chip *imx; |
240 | struct resource *r; | 240 | struct resource *r; |
241 | int ret = 0; | 241 | int ret = 0; |
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c index 015a82235620..14106440294f 100644 --- a/drivers/pwm/pwm-lpc32xx.c +++ b/drivers/pwm/pwm-lpc32xx.c | |||
@@ -49,9 +49,24 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
49 | c = 0; /* 0 set division by 256 */ | 49 | c = 0; /* 0 set division by 256 */ |
50 | period_cycles = c; | 50 | period_cycles = c; |
51 | 51 | ||
52 | /* The duty-cycle value is as follows: | ||
53 | * | ||
54 | * DUTY-CYCLE HIGH LEVEL | ||
55 | * 1 99.9% | ||
56 | * 25 90.0% | ||
57 | * 128 50.0% | ||
58 | * 220 10.0% | ||
59 | * 255 0.1% | ||
60 | * 0 0.0% | ||
61 | * | ||
62 | * In other words, the register value is duty-cycle % 256 with | ||
63 | * duty-cycle in the range 1-256. | ||
64 | */ | ||
52 | c = 256 * duty_ns; | 65 | c = 256 * duty_ns; |
53 | do_div(c, period_ns); | 66 | do_div(c, period_ns); |
54 | duty_cycles = c; | 67 | if (c > 255) |
68 | c = 255; | ||
69 | duty_cycles = 256 - c; | ||
55 | 70 | ||
56 | writel(PWM_ENABLE | PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles), | 71 | writel(PWM_ENABLE | PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles), |
57 | lpc32xx->base + (pwm->hwpwm << 2)); | 72 | lpc32xx->base + (pwm->hwpwm << 2)); |
@@ -106,6 +121,7 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev) | |||
106 | lpc32xx->chip.dev = &pdev->dev; | 121 | lpc32xx->chip.dev = &pdev->dev; |
107 | lpc32xx->chip.ops = &lpc32xx_pwm_ops; | 122 | lpc32xx->chip.ops = &lpc32xx_pwm_ops; |
108 | lpc32xx->chip.npwm = 2; | 123 | lpc32xx->chip.npwm = 2; |
124 | lpc32xx->chip.base = -1; | ||
109 | 125 | ||
110 | ret = pwmchip_add(&lpc32xx->chip); | 126 | ret = pwmchip_add(&lpc32xx->chip); |
111 | if (ret < 0) { | 127 | if (ret < 0) { |
@@ -121,8 +137,11 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev) | |||
121 | static int lpc32xx_pwm_remove(struct platform_device *pdev) | 137 | static int lpc32xx_pwm_remove(struct platform_device *pdev) |
122 | { | 138 | { |
123 | struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev); | 139 | struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev); |
140 | unsigned int i; | ||
141 | |||
142 | for (i = 0; i < lpc32xx->chip.npwm; i++) | ||
143 | pwm_disable(&lpc32xx->chip.pwms[i]); | ||
124 | 144 | ||
125 | clk_disable(lpc32xx->clk); | ||
126 | return pwmchip_remove(&lpc32xx->chip); | 145 | return pwmchip_remove(&lpc32xx->chip); |
127 | } | 146 | } |
128 | 147 | ||
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c index e9b15d099c03..5207e6cd8648 100644 --- a/drivers/pwm/pwm-samsung.c +++ b/drivers/pwm/pwm-samsung.c | |||
@@ -222,6 +222,7 @@ static int s3c_pwm_probe(struct platform_device *pdev) | |||
222 | 222 | ||
223 | /* calculate base of control bits in TCON */ | 223 | /* calculate base of control bits in TCON */ |
224 | s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4; | 224 | s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4; |
225 | s3c->pwm_id = id; | ||
225 | s3c->chip.dev = &pdev->dev; | 226 | s3c->chip.dev = &pdev->dev; |
226 | s3c->chip.ops = &s3c_pwm_ops; | 227 | s3c->chip.ops = &s3c_pwm_ops; |
227 | s3c->chip.base = -1; | 228 | s3c->chip.base = -1; |
diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c new file mode 100644 index 000000000000..83b21d9d5cf9 --- /dev/null +++ b/drivers/pwm/pwm-spear.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * ST Microelectronics SPEAr Pulse Width Modulator driver | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Microelectronics | ||
5 | * Shiraz Hashim <shiraz.hashim@st.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public | ||
8 | * License version 2. This program is licensed "as is" without any | ||
9 | * warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/ioport.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/math64.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/pwm.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/types.h> | ||
24 | |||
25 | #define NUM_PWM 4 | ||
26 | |||
27 | /* PWM registers and bits definitions */ | ||
28 | #define PWMCR 0x00 /* Control Register */ | ||
29 | #define PWMCR_PWM_ENABLE 0x1 | ||
30 | #define PWMCR_PRESCALE_SHIFT 2 | ||
31 | #define PWMCR_MIN_PRESCALE 0x00 | ||
32 | #define PWMCR_MAX_PRESCALE 0x3FFF | ||
33 | |||
34 | #define PWMDCR 0x04 /* Duty Cycle Register */ | ||
35 | #define PWMDCR_MIN_DUTY 0x0001 | ||
36 | #define PWMDCR_MAX_DUTY 0xFFFF | ||
37 | |||
38 | #define PWMPCR 0x08 /* Period Register */ | ||
39 | #define PWMPCR_MIN_PERIOD 0x0001 | ||
40 | #define PWMPCR_MAX_PERIOD 0xFFFF | ||
41 | |||
42 | /* Following only available on 13xx SoCs */ | ||
43 | #define PWMMCR 0x3C /* Master Control Register */ | ||
44 | #define PWMMCR_PWM_ENABLE 0x1 | ||
45 | |||
46 | /** | ||
47 | * struct spear_pwm_chip - struct representing pwm chip | ||
48 | * | ||
49 | * @mmio_base: base address of pwm chip | ||
50 | * @clk: pointer to clk structure of pwm chip | ||
51 | * @chip: linux pwm chip representation | ||
52 | * @dev: pointer to device structure of pwm chip | ||
53 | */ | ||
54 | struct spear_pwm_chip { | ||
55 | void __iomem *mmio_base; | ||
56 | struct clk *clk; | ||
57 | struct pwm_chip chip; | ||
58 | struct device *dev; | ||
59 | }; | ||
60 | |||
61 | static inline struct spear_pwm_chip *to_spear_pwm_chip(struct pwm_chip *chip) | ||
62 | { | ||
63 | return container_of(chip, struct spear_pwm_chip, chip); | ||
64 | } | ||
65 | |||
66 | static inline u32 spear_pwm_readl(struct spear_pwm_chip *chip, unsigned int num, | ||
67 | unsigned long offset) | ||
68 | { | ||
69 | return readl_relaxed(chip->mmio_base + (num << 4) + offset); | ||
70 | } | ||
71 | |||
72 | static inline void spear_pwm_writel(struct spear_pwm_chip *chip, | ||
73 | unsigned int num, unsigned long offset, | ||
74 | unsigned long val) | ||
75 | { | ||
76 | writel_relaxed(val, chip->mmio_base + (num << 4) + offset); | ||
77 | } | ||
78 | |||
79 | static int spear_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
80 | int duty_ns, int period_ns) | ||
81 | { | ||
82 | struct spear_pwm_chip *pc = to_spear_pwm_chip(chip); | ||
83 | u64 val, div, clk_rate; | ||
84 | unsigned long prescale = PWMCR_MIN_PRESCALE, pv, dc; | ||
85 | int ret; | ||
86 | |||
87 | /* | ||
88 | * Find pv, dc and prescale to suit duty_ns and period_ns. This is done | ||
89 | * according to formulas described below: | ||
90 | * | ||
91 | * period_ns = 10^9 * (PRESCALE + 1) * PV / PWM_CLK_RATE | ||
92 | * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE | ||
93 | * | ||
94 | * PV = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1)) | ||
95 | * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1)) | ||
96 | */ | ||
97 | clk_rate = clk_get_rate(pc->clk); | ||
98 | while (1) { | ||
99 | div = 1000000000; | ||
100 | div *= 1 + prescale; | ||
101 | val = clk_rate * period_ns; | ||
102 | pv = div64_u64(val, div); | ||
103 | val = clk_rate * duty_ns; | ||
104 | dc = div64_u64(val, div); | ||
105 | |||
106 | /* if duty_ns and period_ns are not achievable then return */ | ||
107 | if (pv < PWMPCR_MIN_PERIOD || dc < PWMDCR_MIN_DUTY) | ||
108 | return -EINVAL; | ||
109 | |||
110 | /* | ||
111 | * if pv and dc have crossed their upper limit, then increase | ||
112 | * prescale and recalculate pv and dc. | ||
113 | */ | ||
114 | if (pv > PWMPCR_MAX_PERIOD || dc > PWMDCR_MAX_DUTY) { | ||
115 | if (++prescale > PWMCR_MAX_PRESCALE) | ||
116 | return -EINVAL; | ||
117 | continue; | ||
118 | } | ||
119 | break; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * NOTE: the clock to PWM has to be enabled first before writing to the | ||
124 | * registers. | ||
125 | */ | ||
126 | ret = clk_enable(pc->clk); | ||
127 | if (ret) | ||
128 | return ret; | ||
129 | |||
130 | spear_pwm_writel(pc, pwm->hwpwm, PWMCR, | ||
131 | prescale << PWMCR_PRESCALE_SHIFT); | ||
132 | spear_pwm_writel(pc, pwm->hwpwm, PWMDCR, dc); | ||
133 | spear_pwm_writel(pc, pwm->hwpwm, PWMPCR, pv); | ||
134 | clk_disable(pc->clk); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int spear_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
140 | { | ||
141 | struct spear_pwm_chip *pc = to_spear_pwm_chip(chip); | ||
142 | int rc = 0; | ||
143 | u32 val; | ||
144 | |||
145 | rc = clk_enable(pc->clk); | ||
146 | if (!rc) | ||
147 | return rc; | ||
148 | |||
149 | val = spear_pwm_readl(pc, pwm->hwpwm, PWMCR); | ||
150 | val |= PWMCR_PWM_ENABLE; | ||
151 | spear_pwm_writel(pc, pwm->hwpwm, PWMCR, val); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static void spear_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
157 | { | ||
158 | struct spear_pwm_chip *pc = to_spear_pwm_chip(chip); | ||
159 | u32 val; | ||
160 | |||
161 | val = spear_pwm_readl(pc, pwm->hwpwm, PWMCR); | ||
162 | val &= ~PWMCR_PWM_ENABLE; | ||
163 | spear_pwm_writel(pc, pwm->hwpwm, PWMCR, val); | ||
164 | |||
165 | clk_disable(pc->clk); | ||
166 | } | ||
167 | |||
168 | static const struct pwm_ops spear_pwm_ops = { | ||
169 | .config = spear_pwm_config, | ||
170 | .enable = spear_pwm_enable, | ||
171 | .disable = spear_pwm_disable, | ||
172 | .owner = THIS_MODULE, | ||
173 | }; | ||
174 | |||
175 | static int spear_pwm_probe(struct platform_device *pdev) | ||
176 | { | ||
177 | struct device_node *np = pdev->dev.of_node; | ||
178 | struct spear_pwm_chip *pc; | ||
179 | struct resource *r; | ||
180 | int ret; | ||
181 | u32 val; | ||
182 | |||
183 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
184 | if (!r) { | ||
185 | dev_err(&pdev->dev, "no memory resources defined\n"); | ||
186 | return -ENODEV; | ||
187 | } | ||
188 | |||
189 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); | ||
190 | if (!pc) { | ||
191 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
192 | return -ENOMEM; | ||
193 | } | ||
194 | |||
195 | pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); | ||
196 | if (!pc->mmio_base) | ||
197 | return -EADDRNOTAVAIL; | ||
198 | |||
199 | pc->clk = devm_clk_get(&pdev->dev, NULL); | ||
200 | if (IS_ERR(pc->clk)) | ||
201 | return PTR_ERR(pc->clk); | ||
202 | |||
203 | pc->dev = &pdev->dev; | ||
204 | platform_set_drvdata(pdev, pc); | ||
205 | |||
206 | pc->chip.dev = &pdev->dev; | ||
207 | pc->chip.ops = &spear_pwm_ops; | ||
208 | pc->chip.base = -1; | ||
209 | pc->chip.npwm = NUM_PWM; | ||
210 | |||
211 | ret = clk_prepare(pc->clk); | ||
212 | if (!ret) | ||
213 | return ret; | ||
214 | |||
215 | if (of_device_is_compatible(np, "st,spear1340-pwm")) { | ||
216 | ret = clk_enable(pc->clk); | ||
217 | if (!ret) { | ||
218 | clk_unprepare(pc->clk); | ||
219 | return ret; | ||
220 | } | ||
221 | /* | ||
222 | * Following enables PWM chip, channels would still be | ||
223 | * enabled individually through their control register | ||
224 | */ | ||
225 | val = readl_relaxed(pc->mmio_base + PWMMCR); | ||
226 | val |= PWMMCR_PWM_ENABLE; | ||
227 | writel_relaxed(val, pc->mmio_base + PWMMCR); | ||
228 | |||
229 | clk_disable(pc->clk); | ||
230 | } | ||
231 | |||
232 | ret = pwmchip_add(&pc->chip); | ||
233 | if (!ret) { | ||
234 | clk_unprepare(pc->clk); | ||
235 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); | ||
236 | } | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static int spear_pwm_remove(struct platform_device *pdev) | ||
242 | { | ||
243 | struct spear_pwm_chip *pc = platform_get_drvdata(pdev); | ||
244 | int i; | ||
245 | |||
246 | for (i = 0; i < NUM_PWM; i++) | ||
247 | pwm_disable(&pc->chip.pwms[i]); | ||
248 | |||
249 | /* clk was prepared in probe, hence unprepare it here */ | ||
250 | clk_unprepare(pc->clk); | ||
251 | return pwmchip_remove(&pc->chip); | ||
252 | } | ||
253 | |||
254 | static struct of_device_id spear_pwm_of_match[] = { | ||
255 | { .compatible = "st,spear320-pwm" }, | ||
256 | { .compatible = "st,spear1340-pwm" }, | ||
257 | { } | ||
258 | }; | ||
259 | |||
260 | MODULE_DEVICE_TABLE(of, spear_pwm_of_match); | ||
261 | |||
262 | static struct platform_driver spear_pwm_driver = { | ||
263 | .driver = { | ||
264 | .name = "spear-pwm", | ||
265 | .of_match_table = spear_pwm_of_match, | ||
266 | }, | ||
267 | .probe = spear_pwm_probe, | ||
268 | .remove = spear_pwm_remove, | ||
269 | }; | ||
270 | |||
271 | module_platform_driver(spear_pwm_driver); | ||
272 | |||
273 | MODULE_LICENSE("GPL"); | ||
274 | MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>"); | ||
275 | MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.com>"); | ||
276 | MODULE_ALIAS("platform:spear-pwm"); | ||
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 87c091b245cc..5cf016dd9822 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c | |||
@@ -25,6 +25,10 @@ | |||
25 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
26 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
27 | #include <linux/pwm.h> | 27 | #include <linux/pwm.h> |
28 | #include <linux/of_device.h> | ||
29 | #include <linux/pinctrl/consumer.h> | ||
30 | |||
31 | #include "pwm-tipwmss.h" | ||
28 | 32 | ||
29 | /* ECAP registers and bits definitions */ | 33 | /* ECAP registers and bits definitions */ |
30 | #define CAP1 0x08 | 34 | #define CAP1 0x08 |
@@ -184,12 +188,24 @@ static const struct pwm_ops ecap_pwm_ops = { | |||
184 | .owner = THIS_MODULE, | 188 | .owner = THIS_MODULE, |
185 | }; | 189 | }; |
186 | 190 | ||
191 | static const struct of_device_id ecap_of_match[] = { | ||
192 | { .compatible = "ti,am33xx-ecap" }, | ||
193 | {}, | ||
194 | }; | ||
195 | MODULE_DEVICE_TABLE(of, ecap_of_match); | ||
196 | |||
187 | static int ecap_pwm_probe(struct platform_device *pdev) | 197 | static int ecap_pwm_probe(struct platform_device *pdev) |
188 | { | 198 | { |
189 | int ret; | 199 | int ret; |
190 | struct resource *r; | 200 | struct resource *r; |
191 | struct clk *clk; | 201 | struct clk *clk; |
192 | struct ecap_pwm_chip *pc; | 202 | struct ecap_pwm_chip *pc; |
203 | u16 status; | ||
204 | struct pinctrl *pinctrl; | ||
205 | |||
206 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
207 | if (IS_ERR(pinctrl)) | ||
208 | dev_warn(&pdev->dev, "unable to select pin group\n"); | ||
193 | 209 | ||
194 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); | 210 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); |
195 | if (!pc) { | 211 | if (!pc) { |
@@ -211,6 +227,8 @@ static int ecap_pwm_probe(struct platform_device *pdev) | |||
211 | 227 | ||
212 | pc->chip.dev = &pdev->dev; | 228 | pc->chip.dev = &pdev->dev; |
213 | pc->chip.ops = &ecap_pwm_ops; | 229 | pc->chip.ops = &ecap_pwm_ops; |
230 | pc->chip.of_xlate = of_pwm_xlate_with_flags; | ||
231 | pc->chip.of_pwm_n_cells = 3; | ||
214 | pc->chip.base = -1; | 232 | pc->chip.base = -1; |
215 | pc->chip.npwm = 1; | 233 | pc->chip.npwm = 1; |
216 | 234 | ||
@@ -231,14 +249,40 @@ static int ecap_pwm_probe(struct platform_device *pdev) | |||
231 | } | 249 | } |
232 | 250 | ||
233 | pm_runtime_enable(&pdev->dev); | 251 | pm_runtime_enable(&pdev->dev); |
252 | pm_runtime_get_sync(&pdev->dev); | ||
253 | |||
254 | status = pwmss_submodule_state_change(pdev->dev.parent, | ||
255 | PWMSS_ECAPCLK_EN); | ||
256 | if (!(status & PWMSS_ECAPCLK_EN_ACK)) { | ||
257 | dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); | ||
258 | ret = -EINVAL; | ||
259 | goto pwmss_clk_failure; | ||
260 | } | ||
261 | |||
262 | pm_runtime_put_sync(&pdev->dev); | ||
263 | |||
234 | platform_set_drvdata(pdev, pc); | 264 | platform_set_drvdata(pdev, pc); |
235 | return 0; | 265 | return 0; |
266 | |||
267 | pwmss_clk_failure: | ||
268 | pm_runtime_put_sync(&pdev->dev); | ||
269 | pm_runtime_disable(&pdev->dev); | ||
270 | pwmchip_remove(&pc->chip); | ||
271 | return ret; | ||
236 | } | 272 | } |
237 | 273 | ||
238 | static int ecap_pwm_remove(struct platform_device *pdev) | 274 | static int ecap_pwm_remove(struct platform_device *pdev) |
239 | { | 275 | { |
240 | struct ecap_pwm_chip *pc = platform_get_drvdata(pdev); | 276 | struct ecap_pwm_chip *pc = platform_get_drvdata(pdev); |
241 | 277 | ||
278 | pm_runtime_get_sync(&pdev->dev); | ||
279 | /* | ||
280 | * Due to hardware misbehaviour, acknowledge of the stop_req | ||
281 | * is missing. Hence checking of the status bit skipped. | ||
282 | */ | ||
283 | pwmss_submodule_state_change(pdev->dev.parent, PWMSS_ECAPCLK_STOP_REQ); | ||
284 | pm_runtime_put_sync(&pdev->dev); | ||
285 | |||
242 | pm_runtime_put_sync(&pdev->dev); | 286 | pm_runtime_put_sync(&pdev->dev); |
243 | pm_runtime_disable(&pdev->dev); | 287 | pm_runtime_disable(&pdev->dev); |
244 | return pwmchip_remove(&pc->chip); | 288 | return pwmchip_remove(&pc->chip); |
@@ -246,7 +290,9 @@ static int ecap_pwm_remove(struct platform_device *pdev) | |||
246 | 290 | ||
247 | static struct platform_driver ecap_pwm_driver = { | 291 | static struct platform_driver ecap_pwm_driver = { |
248 | .driver = { | 292 | .driver = { |
249 | .name = "ecap", | 293 | .name = "ecap", |
294 | .owner = THIS_MODULE, | ||
295 | .of_match_table = ecap_of_match, | ||
250 | }, | 296 | }, |
251 | .probe = ecap_pwm_probe, | 297 | .probe = ecap_pwm_probe, |
252 | .remove = ecap_pwm_remove, | 298 | .remove = ecap_pwm_remove, |
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 9ffd389d0c8b..72a6dd40c9ec 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c | |||
@@ -25,6 +25,10 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
28 | #include <linux/of_device.h> | ||
29 | #include <linux/pinctrl/consumer.h> | ||
30 | |||
31 | #include "pwm-tipwmss.h" | ||
28 | 32 | ||
29 | /* EHRPWM registers and bits definitions */ | 33 | /* EHRPWM registers and bits definitions */ |
30 | 34 | ||
@@ -115,6 +119,7 @@ struct ehrpwm_pwm_chip { | |||
115 | void __iomem *mmio_base; | 119 | void __iomem *mmio_base; |
116 | unsigned long period_cycles[NUM_PWM_CHANNEL]; | 120 | unsigned long period_cycles[NUM_PWM_CHANNEL]; |
117 | enum pwm_polarity polarity[NUM_PWM_CHANNEL]; | 121 | enum pwm_polarity polarity[NUM_PWM_CHANNEL]; |
122 | struct clk *tbclk; | ||
118 | }; | 123 | }; |
119 | 124 | ||
120 | static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) | 125 | static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) |
@@ -335,6 +340,9 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
335 | /* Channels polarity can be configured from action qualifier module */ | 340 | /* Channels polarity can be configured from action qualifier module */ |
336 | configure_polarity(pc, pwm->hwpwm); | 341 | configure_polarity(pc, pwm->hwpwm); |
337 | 342 | ||
343 | /* Enable TBCLK before enabling PWM device */ | ||
344 | clk_enable(pc->tbclk); | ||
345 | |||
338 | /* Enable time counter for free_run */ | 346 | /* Enable time counter for free_run */ |
339 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); | 347 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); |
340 | return 0; | 348 | return 0; |
@@ -363,6 +371,9 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
363 | 371 | ||
364 | ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); | 372 | ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); |
365 | 373 | ||
374 | /* Disabling TBCLK on PWM disable */ | ||
375 | clk_disable(pc->tbclk); | ||
376 | |||
366 | /* Stop Time base counter */ | 377 | /* Stop Time base counter */ |
367 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT); | 378 | ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT); |
368 | 379 | ||
@@ -392,12 +403,24 @@ static const struct pwm_ops ehrpwm_pwm_ops = { | |||
392 | .owner = THIS_MODULE, | 403 | .owner = THIS_MODULE, |
393 | }; | 404 | }; |
394 | 405 | ||
406 | static const struct of_device_id ehrpwm_of_match[] = { | ||
407 | { .compatible = "ti,am33xx-ehrpwm" }, | ||
408 | {}, | ||
409 | }; | ||
410 | MODULE_DEVICE_TABLE(of, ehrpwm_of_match); | ||
411 | |||
395 | static int ehrpwm_pwm_probe(struct platform_device *pdev) | 412 | static int ehrpwm_pwm_probe(struct platform_device *pdev) |
396 | { | 413 | { |
397 | int ret; | 414 | int ret; |
398 | struct resource *r; | 415 | struct resource *r; |
399 | struct clk *clk; | 416 | struct clk *clk; |
400 | struct ehrpwm_pwm_chip *pc; | 417 | struct ehrpwm_pwm_chip *pc; |
418 | u16 status; | ||
419 | struct pinctrl *pinctrl; | ||
420 | |||
421 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
422 | if (IS_ERR(pinctrl)) | ||
423 | dev_warn(&pdev->dev, "unable to select pin group\n"); | ||
401 | 424 | ||
402 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); | 425 | pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); |
403 | if (!pc) { | 426 | if (!pc) { |
@@ -419,6 +442,8 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) | |||
419 | 442 | ||
420 | pc->chip.dev = &pdev->dev; | 443 | pc->chip.dev = &pdev->dev; |
421 | pc->chip.ops = &ehrpwm_pwm_ops; | 444 | pc->chip.ops = &ehrpwm_pwm_ops; |
445 | pc->chip.of_xlate = of_pwm_xlate_with_flags; | ||
446 | pc->chip.of_pwm_n_cells = 3; | ||
422 | pc->chip.base = -1; | 447 | pc->chip.base = -1; |
423 | pc->chip.npwm = NUM_PWM_CHANNEL; | 448 | pc->chip.npwm = NUM_PWM_CHANNEL; |
424 | 449 | ||
@@ -432,6 +457,13 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) | |||
432 | if (!pc->mmio_base) | 457 | if (!pc->mmio_base) |
433 | return -EADDRNOTAVAIL; | 458 | return -EADDRNOTAVAIL; |
434 | 459 | ||
460 | /* Acquire tbclk for Time Base EHRPWM submodule */ | ||
461 | pc->tbclk = devm_clk_get(&pdev->dev, "tbclk"); | ||
462 | if (IS_ERR(pc->tbclk)) { | ||
463 | dev_err(&pdev->dev, "Failed to get tbclk\n"); | ||
464 | return PTR_ERR(pc->tbclk); | ||
465 | } | ||
466 | |||
435 | ret = pwmchip_add(&pc->chip); | 467 | ret = pwmchip_add(&pc->chip); |
436 | if (ret < 0) { | 468 | if (ret < 0) { |
437 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); | 469 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); |
@@ -439,14 +471,40 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) | |||
439 | } | 471 | } |
440 | 472 | ||
441 | pm_runtime_enable(&pdev->dev); | 473 | pm_runtime_enable(&pdev->dev); |
474 | pm_runtime_get_sync(&pdev->dev); | ||
475 | |||
476 | status = pwmss_submodule_state_change(pdev->dev.parent, | ||
477 | PWMSS_EPWMCLK_EN); | ||
478 | if (!(status & PWMSS_EPWMCLK_EN_ACK)) { | ||
479 | dev_err(&pdev->dev, "PWMSS config space clock enable failed\n"); | ||
480 | ret = -EINVAL; | ||
481 | goto pwmss_clk_failure; | ||
482 | } | ||
483 | |||
484 | pm_runtime_put_sync(&pdev->dev); | ||
485 | |||
442 | platform_set_drvdata(pdev, pc); | 486 | platform_set_drvdata(pdev, pc); |
443 | return 0; | 487 | return 0; |
488 | |||
489 | pwmss_clk_failure: | ||
490 | pm_runtime_put_sync(&pdev->dev); | ||
491 | pm_runtime_disable(&pdev->dev); | ||
492 | pwmchip_remove(&pc->chip); | ||
493 | return ret; | ||
444 | } | 494 | } |
445 | 495 | ||
446 | static int ehrpwm_pwm_remove(struct platform_device *pdev) | 496 | static int ehrpwm_pwm_remove(struct platform_device *pdev) |
447 | { | 497 | { |
448 | struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); | 498 | struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); |
449 | 499 | ||
500 | pm_runtime_get_sync(&pdev->dev); | ||
501 | /* | ||
502 | * Due to hardware misbehaviour, acknowledge of the stop_req | ||
503 | * is missing. Hence checking of the status bit skipped. | ||
504 | */ | ||
505 | pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ); | ||
506 | pm_runtime_put_sync(&pdev->dev); | ||
507 | |||
450 | pm_runtime_put_sync(&pdev->dev); | 508 | pm_runtime_put_sync(&pdev->dev); |
451 | pm_runtime_disable(&pdev->dev); | 509 | pm_runtime_disable(&pdev->dev); |
452 | return pwmchip_remove(&pc->chip); | 510 | return pwmchip_remove(&pc->chip); |
@@ -454,7 +512,9 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev) | |||
454 | 512 | ||
455 | static struct platform_driver ehrpwm_pwm_driver = { | 513 | static struct platform_driver ehrpwm_pwm_driver = { |
456 | .driver = { | 514 | .driver = { |
457 | .name = "ehrpwm", | 515 | .name = "ehrpwm", |
516 | .owner = THIS_MODULE, | ||
517 | .of_match_table = ehrpwm_of_match, | ||
458 | }, | 518 | }, |
459 | .probe = ehrpwm_pwm_probe, | 519 | .probe = ehrpwm_pwm_probe, |
460 | .remove = ehrpwm_pwm_remove, | 520 | .remove = ehrpwm_pwm_remove, |
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/pwm/pwm-tipwmss.c new file mode 100644 index 000000000000..3448a1c88590 --- /dev/null +++ b/drivers/pwm/pwm-tipwmss.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * TI PWM Subsystem driver | ||
3 | * | ||
4 | * Copyright (C) 2012 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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/pm_runtime.h> | ||
23 | #include <linux/of_device.h> | ||
24 | |||
25 | #include "pwm-tipwmss.h" | ||
26 | |||
27 | #define PWMSS_CLKCONFIG 0x8 /* Clock gating reg */ | ||
28 | #define PWMSS_CLKSTATUS 0xc /* Clock gating status reg */ | ||
29 | |||
30 | struct pwmss_info { | ||
31 | void __iomem *mmio_base; | ||
32 | struct mutex pwmss_lock; | ||
33 | u16 pwmss_clkconfig; | ||
34 | }; | ||
35 | |||
36 | u16 pwmss_submodule_state_change(struct device *dev, int set) | ||
37 | { | ||
38 | struct pwmss_info *info = dev_get_drvdata(dev); | ||
39 | u16 val; | ||
40 | |||
41 | mutex_lock(&info->pwmss_lock); | ||
42 | val = readw(info->mmio_base + PWMSS_CLKCONFIG); | ||
43 | val |= set; | ||
44 | writew(val , info->mmio_base + PWMSS_CLKCONFIG); | ||
45 | mutex_unlock(&info->pwmss_lock); | ||
46 | |||
47 | return readw(info->mmio_base + PWMSS_CLKSTATUS); | ||
48 | } | ||
49 | EXPORT_SYMBOL(pwmss_submodule_state_change); | ||
50 | |||
51 | static const struct of_device_id pwmss_of_match[] = { | ||
52 | { .compatible = "ti,am33xx-pwmss" }, | ||
53 | {}, | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(of, pwmss_of_match); | ||
56 | |||
57 | static int pwmss_probe(struct platform_device *pdev) | ||
58 | { | ||
59 | int ret; | ||
60 | struct resource *r; | ||
61 | struct pwmss_info *info; | ||
62 | struct device_node *node = pdev->dev.of_node; | ||
63 | |||
64 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
65 | if (!info) { | ||
66 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
67 | return -ENOMEM; | ||
68 | } | ||
69 | |||
70 | mutex_init(&info->pwmss_lock); | ||
71 | |||
72 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
73 | if (!r) { | ||
74 | dev_err(&pdev->dev, "no memory resource defined\n"); | ||
75 | return -ENODEV; | ||
76 | } | ||
77 | |||
78 | info->mmio_base = devm_request_and_ioremap(&pdev->dev, r); | ||
79 | if (!info->mmio_base) | ||
80 | return -EADDRNOTAVAIL; | ||
81 | |||
82 | pm_runtime_enable(&pdev->dev); | ||
83 | pm_runtime_get_sync(&pdev->dev); | ||
84 | platform_set_drvdata(pdev, info); | ||
85 | |||
86 | /* Populate all the child nodes here... */ | ||
87 | ret = of_platform_populate(node, NULL, NULL, &pdev->dev); | ||
88 | if (ret) | ||
89 | dev_err(&pdev->dev, "no child node found\n"); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | static int pwmss_remove(struct platform_device *pdev) | ||
95 | { | ||
96 | struct pwmss_info *info = platform_get_drvdata(pdev); | ||
97 | |||
98 | pm_runtime_put_sync(&pdev->dev); | ||
99 | pm_runtime_disable(&pdev->dev); | ||
100 | mutex_destroy(&info->pwmss_lock); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int pwmss_suspend(struct device *dev) | ||
105 | { | ||
106 | struct pwmss_info *info = dev_get_drvdata(dev); | ||
107 | |||
108 | info->pwmss_clkconfig = readw(info->mmio_base + PWMSS_CLKCONFIG); | ||
109 | pm_runtime_put_sync(dev); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int pwmss_resume(struct device *dev) | ||
114 | { | ||
115 | struct pwmss_info *info = dev_get_drvdata(dev); | ||
116 | |||
117 | pm_runtime_get_sync(dev); | ||
118 | writew(info->pwmss_clkconfig, info->mmio_base + PWMSS_CLKCONFIG); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static SIMPLE_DEV_PM_OPS(pwmss_pm_ops, pwmss_suspend, pwmss_resume); | ||
123 | |||
124 | static struct platform_driver pwmss_driver = { | ||
125 | .driver = { | ||
126 | .name = "pwmss", | ||
127 | .owner = THIS_MODULE, | ||
128 | .pm = &pwmss_pm_ops, | ||
129 | .of_match_table = pwmss_of_match, | ||
130 | }, | ||
131 | .probe = pwmss_probe, | ||
132 | .remove = pwmss_remove, | ||
133 | }; | ||
134 | |||
135 | module_platform_driver(pwmss_driver); | ||
136 | |||
137 | MODULE_DESCRIPTION("PWM Subsystem driver"); | ||
138 | MODULE_AUTHOR("Texas Instruments"); | ||
139 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pwm/pwm-tipwmss.h b/drivers/pwm/pwm-tipwmss.h new file mode 100644 index 000000000000..11f76a1e266b --- /dev/null +++ b/drivers/pwm/pwm-tipwmss.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * TI PWM Subsystem driver | ||
3 | * | ||
4 | * Copyright (C) 2012 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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __TIPWMSS_H | ||
19 | #define __TIPWMSS_H | ||
20 | |||
21 | #ifdef CONFIG_PWM_TIPWMSS | ||
22 | /* PWM substem clock gating */ | ||
23 | #define PWMSS_ECAPCLK_EN BIT(0) | ||
24 | #define PWMSS_ECAPCLK_STOP_REQ BIT(1) | ||
25 | #define PWMSS_EPWMCLK_EN BIT(8) | ||
26 | #define PWMSS_EPWMCLK_STOP_REQ BIT(9) | ||
27 | |||
28 | #define PWMSS_ECAPCLK_EN_ACK BIT(0) | ||
29 | #define PWMSS_EPWMCLK_EN_ACK BIT(8) | ||
30 | |||
31 | extern u16 pwmss_submodule_state_change(struct device *dev, int set); | ||
32 | #else | ||
33 | static inline u16 pwmss_submodule_state_change(struct device *dev, int set) | ||
34 | { | ||
35 | /* return success status value */ | ||
36 | return 0xFFFF; | ||
37 | } | ||
38 | #endif | ||
39 | #endif /* __TIPWMSS_H */ | ||
diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c new file mode 100644 index 000000000000..9dfa0f3eca30 --- /dev/null +++ b/drivers/pwm/pwm-twl-led.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * Driver for TWL4030/6030 Pulse Width Modulator used as LED driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments | ||
5 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
6 | * | ||
7 | * This driver is a complete rewrite of the former pwm-twl6030.c authorded by: | ||
8 | * Hemanth V <hemanthv@ti.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published by | ||
12 | * the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
17 | * more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along with | ||
20 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/pwm.h> | ||
26 | #include <linux/i2c/twl.h> | ||
27 | #include <linux/slab.h> | ||
28 | |||
29 | /* | ||
30 | * This driver handles the PWM driven LED terminals of TWL4030 and TWL6030. | ||
31 | * To generate the signal on TWL4030: | ||
32 | * - LEDA uses PWMA | ||
33 | * - LEDB uses PWMB | ||
34 | * TWL6030 has one LED pin with dedicated LEDPWM | ||
35 | */ | ||
36 | |||
37 | #define TWL4030_LED_MAX 0x7f | ||
38 | #define TWL6030_LED_MAX 0xff | ||
39 | |||
40 | /* Registers, bits and macro for TWL4030 */ | ||
41 | #define TWL4030_LEDEN_REG 0x00 | ||
42 | #define TWL4030_PWMA_REG 0x01 | ||
43 | |||
44 | #define TWL4030_LEDXON (1 << 0) | ||
45 | #define TWL4030_LEDXPWM (1 << 4) | ||
46 | #define TWL4030_LED_PINS (TWL4030_LEDXON | TWL4030_LEDXPWM) | ||
47 | #define TWL4030_LED_TOGGLE(led, x) ((x) << (led)) | ||
48 | |||
49 | /* Register, bits and macro for TWL6030 */ | ||
50 | #define TWL6030_LED_PWM_CTRL1 0xf4 | ||
51 | #define TWL6030_LED_PWM_CTRL2 0xf5 | ||
52 | |||
53 | #define TWL6040_LED_MODE_HW 0x00 | ||
54 | #define TWL6040_LED_MODE_ON 0x01 | ||
55 | #define TWL6040_LED_MODE_OFF 0x02 | ||
56 | #define TWL6040_LED_MODE_MASK 0x03 | ||
57 | |||
58 | struct twl_pwmled_chip { | ||
59 | struct pwm_chip chip; | ||
60 | struct mutex mutex; | ||
61 | }; | ||
62 | |||
63 | static inline struct twl_pwmled_chip *to_twl(struct pwm_chip *chip) | ||
64 | { | ||
65 | return container_of(chip, struct twl_pwmled_chip, chip); | ||
66 | } | ||
67 | |||
68 | static int twl4030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
69 | int duty_ns, int period_ns) | ||
70 | { | ||
71 | int duty_cycle = DIV_ROUND_UP(duty_ns * TWL4030_LED_MAX, period_ns) + 1; | ||
72 | u8 pwm_config[2] = { 1, 0 }; | ||
73 | int base, ret; | ||
74 | |||
75 | /* | ||
76 | * To configure the duty period: | ||
77 | * On-cycle is set to 1 (the minimum allowed value) | ||
78 | * The off time of 0 is not configurable, so the mapping is: | ||
79 | * 0 -> off cycle = 2, | ||
80 | * 1 -> off cycle = 2, | ||
81 | * 2 -> off cycle = 3, | ||
82 | * 126 - > off cycle 127, | ||
83 | * 127 - > off cycle 1 | ||
84 | * When on cycle == off cycle the PWM will be always on | ||
85 | */ | ||
86 | if (duty_cycle == 1) | ||
87 | duty_cycle = 2; | ||
88 | else if (duty_cycle > TWL4030_LED_MAX) | ||
89 | duty_cycle = 1; | ||
90 | |||
91 | base = pwm->hwpwm * 2 + TWL4030_PWMA_REG; | ||
92 | |||
93 | pwm_config[1] = duty_cycle; | ||
94 | |||
95 | ret = twl_i2c_write(TWL4030_MODULE_LED, pwm_config, base, 2); | ||
96 | if (ret < 0) | ||
97 | dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label); | ||
98 | |||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static int twl4030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
103 | { | ||
104 | struct twl_pwmled_chip *twl = to_twl(chip); | ||
105 | int ret; | ||
106 | u8 val; | ||
107 | |||
108 | mutex_lock(&twl->mutex); | ||
109 | ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG); | ||
110 | if (ret < 0) { | ||
111 | dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label); | ||
112 | goto out; | ||
113 | } | ||
114 | |||
115 | val |= TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS); | ||
116 | |||
117 | ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG); | ||
118 | if (ret < 0) | ||
119 | dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label); | ||
120 | |||
121 | out: | ||
122 | mutex_unlock(&twl->mutex); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | static void twl4030_pwmled_disable(struct pwm_chip *chip, | ||
127 | struct pwm_device *pwm) | ||
128 | { | ||
129 | struct twl_pwmled_chip *twl = to_twl(chip); | ||
130 | int ret; | ||
131 | u8 val; | ||
132 | |||
133 | mutex_lock(&twl->mutex); | ||
134 | ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG); | ||
135 | if (ret < 0) { | ||
136 | dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label); | ||
137 | goto out; | ||
138 | } | ||
139 | |||
140 | val &= ~TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS); | ||
141 | |||
142 | ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG); | ||
143 | if (ret < 0) | ||
144 | dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label); | ||
145 | |||
146 | out: | ||
147 | mutex_unlock(&twl->mutex); | ||
148 | } | ||
149 | |||
150 | static int twl6030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
151 | int duty_ns, int period_ns) | ||
152 | { | ||
153 | int duty_cycle = (duty_ns * TWL6030_LED_MAX) / period_ns; | ||
154 | u8 on_time; | ||
155 | int ret; | ||
156 | |||
157 | on_time = duty_cycle & 0xff; | ||
158 | |||
159 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, on_time, | ||
160 | TWL6030_LED_PWM_CTRL1); | ||
161 | if (ret < 0) | ||
162 | dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | static int twl6030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
168 | { | ||
169 | struct twl_pwmled_chip *twl = to_twl(chip); | ||
170 | int ret; | ||
171 | u8 val; | ||
172 | |||
173 | mutex_lock(&twl->mutex); | ||
174 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); | ||
175 | if (ret < 0) { | ||
176 | dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", | ||
177 | pwm->label); | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | val &= ~TWL6040_LED_MODE_MASK; | ||
182 | val |= TWL6040_LED_MODE_ON; | ||
183 | |||
184 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); | ||
185 | if (ret < 0) | ||
186 | dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label); | ||
187 | |||
188 | out: | ||
189 | mutex_unlock(&twl->mutex); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static void twl6030_pwmled_disable(struct pwm_chip *chip, | ||
194 | struct pwm_device *pwm) | ||
195 | { | ||
196 | struct twl_pwmled_chip *twl = to_twl(chip); | ||
197 | int ret; | ||
198 | u8 val; | ||
199 | |||
200 | mutex_lock(&twl->mutex); | ||
201 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); | ||
202 | if (ret < 0) { | ||
203 | dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", | ||
204 | pwm->label); | ||
205 | goto out; | ||
206 | } | ||
207 | |||
208 | val &= ~TWL6040_LED_MODE_MASK; | ||
209 | val |= TWL6040_LED_MODE_OFF; | ||
210 | |||
211 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); | ||
212 | if (ret < 0) | ||
213 | dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label); | ||
214 | |||
215 | out: | ||
216 | mutex_unlock(&twl->mutex); | ||
217 | } | ||
218 | |||
219 | static int twl6030_pwmled_request(struct pwm_chip *chip, struct pwm_device *pwm) | ||
220 | { | ||
221 | struct twl_pwmled_chip *twl = to_twl(chip); | ||
222 | int ret; | ||
223 | u8 val; | ||
224 | |||
225 | mutex_lock(&twl->mutex); | ||
226 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); | ||
227 | if (ret < 0) { | ||
228 | dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", | ||
229 | pwm->label); | ||
230 | goto out; | ||
231 | } | ||
232 | |||
233 | val &= ~TWL6040_LED_MODE_MASK; | ||
234 | val |= TWL6040_LED_MODE_OFF; | ||
235 | |||
236 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); | ||
237 | if (ret < 0) | ||
238 | dev_err(chip->dev, "%s: Failed to request PWM\n", pwm->label); | ||
239 | |||
240 | out: | ||
241 | mutex_unlock(&twl->mutex); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static void twl6030_pwmled_free(struct pwm_chip *chip, struct pwm_device *pwm) | ||
246 | { | ||
247 | struct twl_pwmled_chip *twl = to_twl(chip); | ||
248 | int ret; | ||
249 | u8 val; | ||
250 | |||
251 | mutex_lock(&twl->mutex); | ||
252 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); | ||
253 | if (ret < 0) { | ||
254 | dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", | ||
255 | pwm->label); | ||
256 | goto out; | ||
257 | } | ||
258 | |||
259 | val &= ~TWL6040_LED_MODE_MASK; | ||
260 | val |= TWL6040_LED_MODE_HW; | ||
261 | |||
262 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); | ||
263 | if (ret < 0) | ||
264 | dev_err(chip->dev, "%s: Failed to free PWM\n", pwm->label); | ||
265 | |||
266 | out: | ||
267 | mutex_unlock(&twl->mutex); | ||
268 | } | ||
269 | |||
270 | static const struct pwm_ops twl4030_pwmled_ops = { | ||
271 | .enable = twl4030_pwmled_enable, | ||
272 | .disable = twl4030_pwmled_disable, | ||
273 | .config = twl4030_pwmled_config, | ||
274 | }; | ||
275 | |||
276 | static const struct pwm_ops twl6030_pwmled_ops = { | ||
277 | .enable = twl6030_pwmled_enable, | ||
278 | .disable = twl6030_pwmled_disable, | ||
279 | .config = twl6030_pwmled_config, | ||
280 | .request = twl6030_pwmled_request, | ||
281 | .free = twl6030_pwmled_free, | ||
282 | }; | ||
283 | |||
284 | static int twl_pwmled_probe(struct platform_device *pdev) | ||
285 | { | ||
286 | struct twl_pwmled_chip *twl; | ||
287 | int ret; | ||
288 | |||
289 | twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); | ||
290 | if (!twl) | ||
291 | return -ENOMEM; | ||
292 | |||
293 | if (twl_class_is_4030()) { | ||
294 | twl->chip.ops = &twl4030_pwmled_ops; | ||
295 | twl->chip.npwm = 2; | ||
296 | } else { | ||
297 | twl->chip.ops = &twl6030_pwmled_ops; | ||
298 | twl->chip.npwm = 1; | ||
299 | } | ||
300 | |||
301 | twl->chip.dev = &pdev->dev; | ||
302 | twl->chip.base = -1; | ||
303 | |||
304 | mutex_init(&twl->mutex); | ||
305 | |||
306 | ret = pwmchip_add(&twl->chip); | ||
307 | if (ret < 0) | ||
308 | return ret; | ||
309 | |||
310 | platform_set_drvdata(pdev, twl); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int twl_pwmled_remove(struct platform_device *pdev) | ||
316 | { | ||
317 | struct twl_pwmled_chip *twl = platform_get_drvdata(pdev); | ||
318 | |||
319 | return pwmchip_remove(&twl->chip); | ||
320 | } | ||
321 | |||
322 | #ifdef CONFIG_OF | ||
323 | static struct of_device_id twl_pwmled_of_match[] = { | ||
324 | { .compatible = "ti,twl4030-pwmled" }, | ||
325 | { .compatible = "ti,twl6030-pwmled" }, | ||
326 | { }, | ||
327 | }; | ||
328 | MODULE_DEVICE_TABLE(of, twl_pwmled_of_match); | ||
329 | #endif | ||
330 | |||
331 | static struct platform_driver twl_pwmled_driver = { | ||
332 | .driver = { | ||
333 | .name = "twl-pwmled", | ||
334 | .of_match_table = of_match_ptr(twl_pwmled_of_match), | ||
335 | }, | ||
336 | .probe = twl_pwmled_probe, | ||
337 | .remove = twl_pwmled_remove, | ||
338 | }; | ||
339 | module_platform_driver(twl_pwmled_driver); | ||
340 | |||
341 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | ||
342 | MODULE_DESCRIPTION("PWM driver for TWL4030 and TWL6030 LED outputs"); | ||
343 | MODULE_ALIAS("platform:twl-pwmled"); | ||
344 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pwm/pwm-twl.c b/drivers/pwm/pwm-twl.c new file mode 100644 index 000000000000..e65db95d5e59 --- /dev/null +++ b/drivers/pwm/pwm-twl.c | |||
@@ -0,0 +1,359 @@ | |||
1 | /* | ||
2 | * Driver for TWL4030/6030 Generic Pulse Width Modulator | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments | ||
5 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/pwm.h> | ||
23 | #include <linux/i2c/twl.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | /* | ||
27 | * This driver handles the PWMs of TWL4030 and TWL6030. | ||
28 | * The TRM names for the PWMs on TWL4030 are: PWM0, PWM1 | ||
29 | * TWL6030 also have two PWMs named in the TRM as PWM1, PWM2 | ||
30 | */ | ||
31 | |||
32 | #define TWL_PWM_MAX 0x7f | ||
33 | |||
34 | /* Registers, bits and macro for TWL4030 */ | ||
35 | #define TWL4030_GPBR1_REG 0x0c | ||
36 | #define TWL4030_PMBR1_REG 0x0d | ||
37 | |||
38 | /* GPBR1 register bits */ | ||
39 | #define TWL4030_PWMXCLK_ENABLE (1 << 0) | ||
40 | #define TWL4030_PWMX_ENABLE (1 << 2) | ||
41 | #define TWL4030_PWMX_BITS (TWL4030_PWMX_ENABLE | TWL4030_PWMXCLK_ENABLE) | ||
42 | #define TWL4030_PWM_TOGGLE(pwm, x) ((x) << (pwm)) | ||
43 | |||
44 | /* PMBR1 register bits */ | ||
45 | #define TWL4030_GPIO6_PWM0_MUTE_MASK (0x03 << 2) | ||
46 | #define TWL4030_GPIO6_PWM0_MUTE_PWM0 (0x01 << 2) | ||
47 | #define TWL4030_GPIO7_VIBRASYNC_PWM1_MASK (0x03 << 4) | ||
48 | #define TWL4030_GPIO7_VIBRASYNC_PWM1_PWM1 (0x03 << 4) | ||
49 | |||
50 | /* Register, bits and macro for TWL6030 */ | ||
51 | #define TWL6030_TOGGLE3_REG 0x92 | ||
52 | |||
53 | #define TWL6030_PWMXR (1 << 0) | ||
54 | #define TWL6030_PWMXS (1 << 1) | ||
55 | #define TWL6030_PWMXEN (1 << 2) | ||
56 | #define TWL6030_PWM_TOGGLE(pwm, x) ((x) << (pwm * 3)) | ||
57 | |||
58 | struct twl_pwm_chip { | ||
59 | struct pwm_chip chip; | ||
60 | struct mutex mutex; | ||
61 | u8 twl6030_toggle3; | ||
62 | u8 twl4030_pwm_mux; | ||
63 | }; | ||
64 | |||
65 | static inline struct twl_pwm_chip *to_twl(struct pwm_chip *chip) | ||
66 | { | ||
67 | return container_of(chip, struct twl_pwm_chip, chip); | ||
68 | } | ||
69 | |||
70 | static int twl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
71 | int duty_ns, int period_ns) | ||
72 | { | ||
73 | int duty_cycle = DIV_ROUND_UP(duty_ns * TWL_PWM_MAX, period_ns) + 1; | ||
74 | u8 pwm_config[2] = { 1, 0 }; | ||
75 | int base, ret; | ||
76 | |||
77 | /* | ||
78 | * To configure the duty period: | ||
79 | * On-cycle is set to 1 (the minimum allowed value) | ||
80 | * The off time of 0 is not configurable, so the mapping is: | ||
81 | * 0 -> off cycle = 2, | ||
82 | * 1 -> off cycle = 2, | ||
83 | * 2 -> off cycle = 3, | ||
84 | * 126 - > off cycle 127, | ||
85 | * 127 - > off cycle 1 | ||
86 | * When on cycle == off cycle the PWM will be always on | ||
87 | */ | ||
88 | if (duty_cycle == 1) | ||
89 | duty_cycle = 2; | ||
90 | else if (duty_cycle > TWL_PWM_MAX) | ||
91 | duty_cycle = 1; | ||
92 | |||
93 | base = pwm->hwpwm * 3; | ||
94 | |||
95 | pwm_config[1] = duty_cycle; | ||
96 | |||
97 | ret = twl_i2c_write(TWL_MODULE_PWM, pwm_config, base, 2); | ||
98 | if (ret < 0) | ||
99 | dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static int twl4030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
105 | { | ||
106 | struct twl_pwm_chip *twl = to_twl(chip); | ||
107 | int ret; | ||
108 | u8 val; | ||
109 | |||
110 | mutex_lock(&twl->mutex); | ||
111 | ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG); | ||
112 | if (ret < 0) { | ||
113 | dev_err(chip->dev, "%s: Failed to read GPBR1\n", pwm->label); | ||
114 | goto out; | ||
115 | } | ||
116 | |||
117 | val |= TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMXCLK_ENABLE); | ||
118 | |||
119 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); | ||
120 | if (ret < 0) | ||
121 | dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label); | ||
122 | |||
123 | val |= TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMX_ENABLE); | ||
124 | |||
125 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); | ||
126 | if (ret < 0) | ||
127 | dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label); | ||
128 | |||
129 | out: | ||
130 | mutex_unlock(&twl->mutex); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static void twl4030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
135 | { | ||
136 | struct twl_pwm_chip *twl = to_twl(chip); | ||
137 | int ret; | ||
138 | u8 val; | ||
139 | |||
140 | mutex_lock(&twl->mutex); | ||
141 | ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG); | ||
142 | if (ret < 0) { | ||
143 | dev_err(chip->dev, "%s: Failed to read GPBR1\n", pwm->label); | ||
144 | goto out; | ||
145 | } | ||
146 | |||
147 | val &= ~TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMX_ENABLE); | ||
148 | |||
149 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); | ||
150 | if (ret < 0) | ||
151 | dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label); | ||
152 | |||
153 | val &= ~TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMXCLK_ENABLE); | ||
154 | |||
155 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); | ||
156 | if (ret < 0) | ||
157 | dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label); | ||
158 | |||
159 | out: | ||
160 | mutex_unlock(&twl->mutex); | ||
161 | } | ||
162 | |||
163 | static int twl4030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) | ||
164 | { | ||
165 | struct twl_pwm_chip *twl = to_twl(chip); | ||
166 | int ret; | ||
167 | u8 val, mask, bits; | ||
168 | |||
169 | if (pwm->hwpwm == 1) { | ||
170 | mask = TWL4030_GPIO7_VIBRASYNC_PWM1_MASK; | ||
171 | bits = TWL4030_GPIO7_VIBRASYNC_PWM1_PWM1; | ||
172 | } else { | ||
173 | mask = TWL4030_GPIO6_PWM0_MUTE_MASK; | ||
174 | bits = TWL4030_GPIO6_PWM0_MUTE_PWM0; | ||
175 | } | ||
176 | |||
177 | mutex_lock(&twl->mutex); | ||
178 | ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG); | ||
179 | if (ret < 0) { | ||
180 | dev_err(chip->dev, "%s: Failed to read PMBR1\n", pwm->label); | ||
181 | goto out; | ||
182 | } | ||
183 | |||
184 | /* Save the current MUX configuration for the PWM */ | ||
185 | twl->twl4030_pwm_mux &= ~mask; | ||
186 | twl->twl4030_pwm_mux |= (val & mask); | ||
187 | |||
188 | /* Select PWM functionality */ | ||
189 | val &= ~mask; | ||
190 | val |= bits; | ||
191 | |||
192 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG); | ||
193 | if (ret < 0) | ||
194 | dev_err(chip->dev, "%s: Failed to request PWM\n", pwm->label); | ||
195 | |||
196 | out: | ||
197 | mutex_unlock(&twl->mutex); | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | static void twl4030_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | ||
202 | { | ||
203 | struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip, | ||
204 | chip); | ||
205 | int ret; | ||
206 | u8 val, mask; | ||
207 | |||
208 | if (pwm->hwpwm == 1) | ||
209 | mask = TWL4030_GPIO7_VIBRASYNC_PWM1_MASK; | ||
210 | else | ||
211 | mask = TWL4030_GPIO6_PWM0_MUTE_MASK; | ||
212 | |||
213 | mutex_lock(&twl->mutex); | ||
214 | ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG); | ||
215 | if (ret < 0) { | ||
216 | dev_err(chip->dev, "%s: Failed to read PMBR1\n", pwm->label); | ||
217 | goto out; | ||
218 | } | ||
219 | |||
220 | /* Restore the MUX configuration for the PWM */ | ||
221 | val &= ~mask; | ||
222 | val |= (twl->twl4030_pwm_mux & mask); | ||
223 | |||
224 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG); | ||
225 | if (ret < 0) | ||
226 | dev_err(chip->dev, "%s: Failed to free PWM\n", pwm->label); | ||
227 | |||
228 | out: | ||
229 | mutex_unlock(&twl->mutex); | ||
230 | } | ||
231 | |||
232 | static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
233 | { | ||
234 | struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip, | ||
235 | chip); | ||
236 | int ret; | ||
237 | u8 val; | ||
238 | |||
239 | mutex_lock(&twl->mutex); | ||
240 | val = twl->twl6030_toggle3; | ||
241 | val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN); | ||
242 | val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXR); | ||
243 | |||
244 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG); | ||
245 | if (ret < 0) { | ||
246 | dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label); | ||
247 | goto out; | ||
248 | } | ||
249 | |||
250 | twl->twl6030_toggle3 = val; | ||
251 | out: | ||
252 | mutex_unlock(&twl->mutex); | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
257 | { | ||
258 | struct twl_pwm_chip *twl = container_of(chip, struct twl_pwm_chip, | ||
259 | chip); | ||
260 | int ret; | ||
261 | u8 val; | ||
262 | |||
263 | mutex_lock(&twl->mutex); | ||
264 | val = twl->twl6030_toggle3; | ||
265 | val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXR); | ||
266 | val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN); | ||
267 | |||
268 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG); | ||
269 | if (ret < 0) { | ||
270 | dev_err(chip->dev, "%s: Failed to read TOGGLE3\n", pwm->label); | ||
271 | goto out; | ||
272 | } | ||
273 | |||
274 | val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN); | ||
275 | |||
276 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG); | ||
277 | if (ret < 0) { | ||
278 | dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label); | ||
279 | goto out; | ||
280 | } | ||
281 | |||
282 | twl->twl6030_toggle3 = val; | ||
283 | out: | ||
284 | mutex_unlock(&twl->mutex); | ||
285 | } | ||
286 | |||
287 | static const struct pwm_ops twl4030_pwm_ops = { | ||
288 | .config = twl_pwm_config, | ||
289 | .enable = twl4030_pwm_enable, | ||
290 | .disable = twl4030_pwm_disable, | ||
291 | .request = twl4030_pwm_request, | ||
292 | .free = twl4030_pwm_free, | ||
293 | }; | ||
294 | |||
295 | static const struct pwm_ops twl6030_pwm_ops = { | ||
296 | .config = twl_pwm_config, | ||
297 | .enable = twl6030_pwm_enable, | ||
298 | .disable = twl6030_pwm_disable, | ||
299 | }; | ||
300 | |||
301 | static int twl_pwm_probe(struct platform_device *pdev) | ||
302 | { | ||
303 | struct twl_pwm_chip *twl; | ||
304 | int ret; | ||
305 | |||
306 | twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); | ||
307 | if (!twl) | ||
308 | return -ENOMEM; | ||
309 | |||
310 | if (twl_class_is_4030()) | ||
311 | twl->chip.ops = &twl4030_pwm_ops; | ||
312 | else | ||
313 | twl->chip.ops = &twl6030_pwm_ops; | ||
314 | |||
315 | twl->chip.dev = &pdev->dev; | ||
316 | twl->chip.base = -1; | ||
317 | twl->chip.npwm = 2; | ||
318 | |||
319 | mutex_init(&twl->mutex); | ||
320 | |||
321 | ret = pwmchip_add(&twl->chip); | ||
322 | if (ret < 0) | ||
323 | return ret; | ||
324 | |||
325 | platform_set_drvdata(pdev, twl); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int twl_pwm_remove(struct platform_device *pdev) | ||
331 | { | ||
332 | struct twl_pwm_chip *twl = platform_get_drvdata(pdev); | ||
333 | |||
334 | return pwmchip_remove(&twl->chip); | ||
335 | } | ||
336 | |||
337 | #ifdef CONFIG_OF | ||
338 | static struct of_device_id twl_pwm_of_match[] = { | ||
339 | { .compatible = "ti,twl4030-pwm" }, | ||
340 | { .compatible = "ti,twl6030-pwm" }, | ||
341 | { }, | ||
342 | }; | ||
343 | MODULE_DEVICE_TABLE(of, twl_pwm_of_match); | ||
344 | #endif | ||
345 | |||
346 | static struct platform_driver twl_pwm_driver = { | ||
347 | .driver = { | ||
348 | .name = "twl-pwm", | ||
349 | .of_match_table = of_match_ptr(twl_pwm_of_match), | ||
350 | }, | ||
351 | .probe = twl_pwm_probe, | ||
352 | .remove = twl_pwm_remove, | ||
353 | }; | ||
354 | module_platform_driver(twl_pwm_driver); | ||
355 | |||
356 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | ||
357 | MODULE_DESCRIPTION("PWM driver for TWL4030 and TWL6030"); | ||
358 | MODULE_ALIAS("platform:twl-pwm"); | ||
359 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pwm/pwm-twl6030.c b/drivers/pwm/pwm-twl6030.c deleted file mode 100644 index 378a7e286366..000000000000 --- a/drivers/pwm/pwm-twl6030.c +++ /dev/null | |||
@@ -1,184 +0,0 @@ | |||
1 | /* | ||
2 | * twl6030_pwm.c | ||
3 | * Driver for PHOENIX (TWL6030) Pulse Width Modulator | ||
4 | * | ||
5 | * Copyright (C) 2010 Texas Instruments | ||
6 | * Author: Hemanth V <hemanthv@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/pwm.h> | ||
24 | #include <linux/i2c/twl.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #define LED_PWM_CTRL1 0xF4 | ||
28 | #define LED_PWM_CTRL2 0xF5 | ||
29 | |||
30 | /* Max value for CTRL1 register */ | ||
31 | #define PWM_CTRL1_MAX 255 | ||
32 | |||
33 | /* Pull down disable */ | ||
34 | #define PWM_CTRL2_DIS_PD (1 << 6) | ||
35 | |||
36 | /* Current control 2.5 milli Amps */ | ||
37 | #define PWM_CTRL2_CURR_02 (2 << 4) | ||
38 | |||
39 | /* LED supply source */ | ||
40 | #define PWM_CTRL2_SRC_VAC (1 << 2) | ||
41 | |||
42 | /* LED modes */ | ||
43 | #define PWM_CTRL2_MODE_HW (0 << 0) | ||
44 | #define PWM_CTRL2_MODE_SW (1 << 0) | ||
45 | #define PWM_CTRL2_MODE_DIS (2 << 0) | ||
46 | |||
47 | #define PWM_CTRL2_MODE_MASK 0x3 | ||
48 | |||
49 | struct twl6030_pwm_chip { | ||
50 | struct pwm_chip chip; | ||
51 | }; | ||
52 | |||
53 | static int twl6030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) | ||
54 | { | ||
55 | int ret; | ||
56 | u8 val; | ||
57 | |||
58 | /* Configure PWM */ | ||
59 | val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC | | ||
60 | PWM_CTRL2_MODE_HW; | ||
61 | |||
62 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
63 | if (ret < 0) { | ||
64 | dev_err(chip->dev, "%s: Failed to configure PWM, Error %d\n", | ||
65 | pwm->label, ret); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int twl6030_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||
73 | int duty_ns, int period_ns) | ||
74 | { | ||
75 | u8 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns; | ||
76 | int ret; | ||
77 | |||
78 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1); | ||
79 | if (ret < 0) { | ||
80 | pr_err("%s: Failed to configure PWM, Error %d\n", | ||
81 | pwm->label, ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
89 | { | ||
90 | int ret; | ||
91 | u8 val; | ||
92 | |||
93 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
94 | if (ret < 0) { | ||
95 | dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n", | ||
96 | pwm->label, ret); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | /* Change mode to software control */ | ||
101 | val &= ~PWM_CTRL2_MODE_MASK; | ||
102 | val |= PWM_CTRL2_MODE_SW; | ||
103 | |||
104 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
105 | if (ret < 0) { | ||
106 | dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n", | ||
107 | pwm->label, ret); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||
116 | { | ||
117 | int ret; | ||
118 | u8 val; | ||
119 | |||
120 | ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2); | ||
121 | if (ret < 0) { | ||
122 | dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n", | ||
123 | pwm->label, ret); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | val &= ~PWM_CTRL2_MODE_MASK; | ||
128 | val |= PWM_CTRL2_MODE_HW; | ||
129 | |||
130 | ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2); | ||
131 | if (ret < 0) { | ||
132 | dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n", | ||
133 | pwm->label, ret); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | static const struct pwm_ops twl6030_pwm_ops = { | ||
138 | .request = twl6030_pwm_request, | ||
139 | .config = twl6030_pwm_config, | ||
140 | .enable = twl6030_pwm_enable, | ||
141 | .disable = twl6030_pwm_disable, | ||
142 | }; | ||
143 | |||
144 | static int twl6030_pwm_probe(struct platform_device *pdev) | ||
145 | { | ||
146 | struct twl6030_pwm_chip *twl6030; | ||
147 | int ret; | ||
148 | |||
149 | twl6030 = devm_kzalloc(&pdev->dev, sizeof(*twl6030), GFP_KERNEL); | ||
150 | if (!twl6030) | ||
151 | return -ENOMEM; | ||
152 | |||
153 | twl6030->chip.dev = &pdev->dev; | ||
154 | twl6030->chip.ops = &twl6030_pwm_ops; | ||
155 | twl6030->chip.base = -1; | ||
156 | twl6030->chip.npwm = 1; | ||
157 | |||
158 | ret = pwmchip_add(&twl6030->chip); | ||
159 | if (ret < 0) | ||
160 | return ret; | ||
161 | |||
162 | platform_set_drvdata(pdev, twl6030); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int twl6030_pwm_remove(struct platform_device *pdev) | ||
168 | { | ||
169 | struct twl6030_pwm_chip *twl6030 = platform_get_drvdata(pdev); | ||
170 | |||
171 | return pwmchip_remove(&twl6030->chip); | ||
172 | } | ||
173 | |||
174 | static struct platform_driver twl6030_pwm_driver = { | ||
175 | .driver = { | ||
176 | .name = "twl6030-pwm", | ||
177 | }, | ||
178 | .probe = twl6030_pwm_probe, | ||
179 | .remove = twl6030_pwm_remove, | ||
180 | }; | ||
181 | module_platform_driver(twl6030_pwm_driver); | ||
182 | |||
183 | MODULE_ALIAS("platform:twl6030-pwm"); | ||
184 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index ad14389b7144..b0ba2d403439 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/pwm/pwm-vt8500.c | 2 | * drivers/pwm/pwm-vt8500.c |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> | 4 | * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> |
5 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> | ||
5 | * | 6 | * |
6 | * This software is licensed under the terms of the GNU General Public | 7 | * This software is licensed under the terms of the GNU General Public |
7 | * License version 2, as published by the Free Software Foundation, and | 8 | * License version 2, as published by the Free Software Foundation, and |
@@ -21,14 +22,24 @@ | |||
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | #include <linux/pwm.h> | 23 | #include <linux/pwm.h> |
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/clk.h> | ||
24 | 26 | ||
25 | #include <asm/div64.h> | 27 | #include <asm/div64.h> |
26 | 28 | ||
27 | #define VT8500_NR_PWMS 4 | 29 | #include <linux/of.h> |
30 | #include <linux/of_device.h> | ||
31 | #include <linux/of_address.h> | ||
32 | |||
33 | /* | ||
34 | * SoC architecture allocates register space for 4 PWMs but only | ||
35 | * 2 are currently implemented. | ||
36 | */ | ||
37 | #define VT8500_NR_PWMS 2 | ||
28 | 38 | ||
29 | struct vt8500_chip { | 39 | struct vt8500_chip { |
30 | struct pwm_chip chip; | 40 | struct pwm_chip chip; |
31 | void __iomem *base; | 41 | void __iomem *base; |
42 | struct clk *clk; | ||
32 | }; | 43 | }; |
33 | 44 | ||
34 | #define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) | 45 | #define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) |
@@ -51,8 +62,15 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
51 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); | 62 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); |
52 | unsigned long long c; | 63 | unsigned long long c; |
53 | unsigned long period_cycles, prescale, pv, dc; | 64 | unsigned long period_cycles, prescale, pv, dc; |
65 | int err; | ||
54 | 66 | ||
55 | c = 25000000/2; /* wild guess --- need to implement clocks */ | 67 | err = clk_enable(vt8500->clk); |
68 | if (err < 0) { | ||
69 | dev_err(chip->dev, "failed to enable clock\n"); | ||
70 | return err; | ||
71 | } | ||
72 | |||
73 | c = clk_get_rate(vt8500->clk); | ||
56 | c = c * period_ns; | 74 | c = c * period_ns; |
57 | do_div(c, 1000000000); | 75 | do_div(c, 1000000000); |
58 | period_cycles = c; | 76 | period_cycles = c; |
@@ -64,8 +82,10 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
64 | if (pv > 4095) | 82 | if (pv > 4095) |
65 | pv = 4095; | 83 | pv = 4095; |
66 | 84 | ||
67 | if (prescale > 1023) | 85 | if (prescale > 1023) { |
86 | clk_disable(vt8500->clk); | ||
68 | return -EINVAL; | 87 | return -EINVAL; |
88 | } | ||
69 | 89 | ||
70 | c = (unsigned long long)pv * duty_ns; | 90 | c = (unsigned long long)pv * duty_ns; |
71 | do_div(c, period_ns); | 91 | do_div(c, period_ns); |
@@ -80,13 +100,21 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
80 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 3)); | 100 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 3)); |
81 | writel(dc, vt8500->base + 0xc + (pwm->hwpwm << 4)); | 101 | writel(dc, vt8500->base + 0xc + (pwm->hwpwm << 4)); |
82 | 102 | ||
103 | clk_disable(vt8500->clk); | ||
83 | return 0; | 104 | return 0; |
84 | } | 105 | } |
85 | 106 | ||
86 | static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | 107 | static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
87 | { | 108 | { |
109 | int err; | ||
88 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); | 110 | struct vt8500_chip *vt8500 = to_vt8500_chip(chip); |
89 | 111 | ||
112 | err = clk_enable(vt8500->clk); | ||
113 | if (err < 0) { | ||
114 | dev_err(chip->dev, "failed to enable clock\n"); | ||
115 | return err; | ||
116 | } | ||
117 | |||
90 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); | 118 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); |
91 | writel(5, vt8500->base + (pwm->hwpwm << 4)); | 119 | writel(5, vt8500->base + (pwm->hwpwm << 4)); |
92 | return 0; | 120 | return 0; |
@@ -98,6 +126,8 @@ static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
98 | 126 | ||
99 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); | 127 | pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); |
100 | writel(0, vt8500->base + (pwm->hwpwm << 4)); | 128 | writel(0, vt8500->base + (pwm->hwpwm << 4)); |
129 | |||
130 | clk_disable(vt8500->clk); | ||
101 | } | 131 | } |
102 | 132 | ||
103 | static struct pwm_ops vt8500_pwm_ops = { | 133 | static struct pwm_ops vt8500_pwm_ops = { |
@@ -107,12 +137,24 @@ static struct pwm_ops vt8500_pwm_ops = { | |||
107 | .owner = THIS_MODULE, | 137 | .owner = THIS_MODULE, |
108 | }; | 138 | }; |
109 | 139 | ||
110 | static int __devinit pwm_probe(struct platform_device *pdev) | 140 | static const struct of_device_id vt8500_pwm_dt_ids[] = { |
141 | { .compatible = "via,vt8500-pwm", }, | ||
142 | { /* Sentinel */ } | ||
143 | }; | ||
144 | MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids); | ||
145 | |||
146 | static int vt8500_pwm_probe(struct platform_device *pdev) | ||
111 | { | 147 | { |
112 | struct vt8500_chip *chip; | 148 | struct vt8500_chip *chip; |
113 | struct resource *r; | 149 | struct resource *r; |
150 | struct device_node *np = pdev->dev.of_node; | ||
114 | int ret; | 151 | int ret; |
115 | 152 | ||
153 | if (!np) { | ||
154 | dev_err(&pdev->dev, "invalid devicetree node\n"); | ||
155 | return -EINVAL; | ||
156 | } | ||
157 | |||
116 | chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); | 158 | chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); |
117 | if (chip == NULL) { | 159 | if (chip == NULL) { |
118 | dev_err(&pdev->dev, "failed to allocate memory\n"); | 160 | dev_err(&pdev->dev, "failed to allocate memory\n"); |
@@ -124,6 +166,12 @@ static int __devinit pwm_probe(struct platform_device *pdev) | |||
124 | chip->chip.base = -1; | 166 | chip->chip.base = -1; |
125 | chip->chip.npwm = VT8500_NR_PWMS; | 167 | chip->chip.npwm = VT8500_NR_PWMS; |
126 | 168 | ||
169 | chip->clk = devm_clk_get(&pdev->dev, NULL); | ||
170 | if (IS_ERR(chip->clk)) { | ||
171 | dev_err(&pdev->dev, "clock source not specified\n"); | ||
172 | return PTR_ERR(chip->clk); | ||
173 | } | ||
174 | |||
127 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 175 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
128 | if (r == NULL) { | 176 | if (r == NULL) { |
129 | dev_err(&pdev->dev, "no memory resource defined\n"); | 177 | dev_err(&pdev->dev, "no memory resource defined\n"); |
@@ -131,18 +179,26 @@ static int __devinit pwm_probe(struct platform_device *pdev) | |||
131 | } | 179 | } |
132 | 180 | ||
133 | chip->base = devm_request_and_ioremap(&pdev->dev, r); | 181 | chip->base = devm_request_and_ioremap(&pdev->dev, r); |
134 | if (chip->base == NULL) | 182 | if (!chip->base) |
135 | return -EADDRNOTAVAIL; | 183 | return -EADDRNOTAVAIL; |
136 | 184 | ||
185 | ret = clk_prepare(chip->clk); | ||
186 | if (ret < 0) { | ||
187 | dev_err(&pdev->dev, "failed to prepare clock\n"); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
137 | ret = pwmchip_add(&chip->chip); | 191 | ret = pwmchip_add(&chip->chip); |
138 | if (ret < 0) | 192 | if (ret < 0) { |
193 | dev_err(&pdev->dev, "failed to add PWM chip\n"); | ||
139 | return ret; | 194 | return ret; |
195 | } | ||
140 | 196 | ||
141 | platform_set_drvdata(pdev, chip); | 197 | platform_set_drvdata(pdev, chip); |
142 | return ret; | 198 | return ret; |
143 | } | 199 | } |
144 | 200 | ||
145 | static int __devexit pwm_remove(struct platform_device *pdev) | 201 | static int vt8500_pwm_remove(struct platform_device *pdev) |
146 | { | 202 | { |
147 | struct vt8500_chip *chip; | 203 | struct vt8500_chip *chip; |
148 | 204 | ||
@@ -150,28 +206,22 @@ static int __devexit pwm_remove(struct platform_device *pdev) | |||
150 | if (chip == NULL) | 206 | if (chip == NULL) |
151 | return -ENODEV; | 207 | return -ENODEV; |
152 | 208 | ||
209 | clk_unprepare(chip->clk); | ||
210 | |||
153 | return pwmchip_remove(&chip->chip); | 211 | return pwmchip_remove(&chip->chip); |
154 | } | 212 | } |
155 | 213 | ||
156 | static struct platform_driver pwm_driver = { | 214 | static struct platform_driver vt8500_pwm_driver = { |
215 | .probe = vt8500_pwm_probe, | ||
216 | .remove = vt8500_pwm_remove, | ||
157 | .driver = { | 217 | .driver = { |
158 | .name = "vt8500-pwm", | 218 | .name = "vt8500-pwm", |
159 | .owner = THIS_MODULE, | 219 | .owner = THIS_MODULE, |
220 | .of_match_table = vt8500_pwm_dt_ids, | ||
160 | }, | 221 | }, |
161 | .probe = pwm_probe, | ||
162 | .remove = __devexit_p(pwm_remove), | ||
163 | }; | 222 | }; |
223 | module_platform_driver(vt8500_pwm_driver); | ||
164 | 224 | ||
165 | static int __init pwm_init(void) | 225 | MODULE_DESCRIPTION("VT8500 PWM Driver"); |
166 | { | 226 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); |
167 | return platform_driver_register(&pwm_driver); | 227 | MODULE_LICENSE("GPL v2"); |
168 | } | ||
169 | arch_initcall(pwm_init); | ||
170 | |||
171 | static void __exit pwm_exit(void) | ||
172 | { | ||
173 | platform_driver_unregister(&pwm_driver); | ||
174 | } | ||
175 | module_exit(pwm_exit); | ||
176 | |||
177 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 75c0c4f5fdf2..ab34497bcfee 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/platform_data/atmel.h> | 22 | #include <linux/platform_data/atmel.h> |
23 | #include <linux/of.h> | ||
23 | 24 | ||
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | #include <asm/gpio.h> | 26 | #include <asm/gpio.h> |
@@ -768,6 +769,10 @@ static int atmel_spi_setup(struct spi_device *spi) | |||
768 | 769 | ||
769 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ | 770 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ |
770 | npcs_pin = (unsigned int)spi->controller_data; | 771 | npcs_pin = (unsigned int)spi->controller_data; |
772 | |||
773 | if (gpio_is_valid(spi->cs_gpio)) | ||
774 | npcs_pin = spi->cs_gpio; | ||
775 | |||
771 | asd = spi->controller_state; | 776 | asd = spi->controller_state; |
772 | if (!asd) { | 777 | if (!asd) { |
773 | asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL); | 778 | asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL); |
@@ -937,8 +942,9 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
937 | /* the spi->mode bits understood by this driver: */ | 942 | /* the spi->mode bits understood by this driver: */ |
938 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 943 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
939 | 944 | ||
945 | master->dev.of_node = pdev->dev.of_node; | ||
940 | master->bus_num = pdev->id; | 946 | master->bus_num = pdev->id; |
941 | master->num_chipselect = 4; | 947 | master->num_chipselect = master->dev.of_node ? 0 : 4; |
942 | master->setup = atmel_spi_setup; | 948 | master->setup = atmel_spi_setup; |
943 | master->transfer = atmel_spi_transfer; | 949 | master->transfer = atmel_spi_transfer; |
944 | master->cleanup = atmel_spi_cleanup; | 950 | master->cleanup = atmel_spi_cleanup; |
@@ -1064,11 +1070,20 @@ static int atmel_spi_resume(struct platform_device *pdev) | |||
1064 | #define atmel_spi_resume NULL | 1070 | #define atmel_spi_resume NULL |
1065 | #endif | 1071 | #endif |
1066 | 1072 | ||
1073 | #if defined(CONFIG_OF) | ||
1074 | static const struct of_device_id atmel_spi_dt_ids[] = { | ||
1075 | { .compatible = "atmel,at91rm9200-spi" }, | ||
1076 | { /* sentinel */ } | ||
1077 | }; | ||
1078 | |||
1079 | MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids); | ||
1080 | #endif | ||
1067 | 1081 | ||
1068 | static struct platform_driver atmel_spi_driver = { | 1082 | static struct platform_driver atmel_spi_driver = { |
1069 | .driver = { | 1083 | .driver = { |
1070 | .name = "atmel_spi", | 1084 | .name = "atmel_spi", |
1071 | .owner = THIS_MODULE, | 1085 | .owner = THIS_MODULE, |
1086 | .of_match_table = of_match_ptr(atmel_spi_dt_ids), | ||
1072 | }, | 1087 | }, |
1073 | .suspend = atmel_spi_suspend, | 1088 | .suspend = atmel_spi_suspend, |
1074 | .resume = atmel_spi_resume, | 1089 | .resume = atmel_spi_resume, |
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 4dd7b7ce5c5a..ad93231a8038 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c | |||
@@ -215,6 +215,10 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
215 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); | 215 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); |
216 | 216 | ||
217 | val = readl(regs + S3C64XX_SPI_CH_CFG); | 217 | val = readl(regs + S3C64XX_SPI_CH_CFG); |
218 | val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON); | ||
219 | writel(val, regs + S3C64XX_SPI_CH_CFG); | ||
220 | |||
221 | val = readl(regs + S3C64XX_SPI_CH_CFG); | ||
218 | val |= S3C64XX_SPI_CH_SW_RST; | 222 | val |= S3C64XX_SPI_CH_SW_RST; |
219 | val &= ~S3C64XX_SPI_CH_HS_EN; | 223 | val &= ~S3C64XX_SPI_CH_HS_EN; |
220 | writel(val, regs + S3C64XX_SPI_CH_CFG); | 224 | writel(val, regs + S3C64XX_SPI_CH_CFG); |
@@ -248,10 +252,6 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
248 | val = readl(regs + S3C64XX_SPI_MODE_CFG); | 252 | val = readl(regs + S3C64XX_SPI_MODE_CFG); |
249 | val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON); | 253 | val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON); |
250 | writel(val, regs + S3C64XX_SPI_MODE_CFG); | 254 | writel(val, regs + S3C64XX_SPI_MODE_CFG); |
251 | |||
252 | val = readl(regs + S3C64XX_SPI_CH_CFG); | ||
253 | val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON); | ||
254 | writel(val, regs + S3C64XX_SPI_CH_CFG); | ||
255 | } | 255 | } |
256 | 256 | ||
257 | static void s3c64xx_spi_dmacb(void *data) | 257 | static void s3c64xx_spi_dmacb(void *data) |
@@ -771,8 +771,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, | |||
771 | if (list_is_last(&xfer->transfer_list, | 771 | if (list_is_last(&xfer->transfer_list, |
772 | &msg->transfers)) | 772 | &msg->transfers)) |
773 | cs_toggle = 1; | 773 | cs_toggle = 1; |
774 | else | ||
775 | disable_cs(sdd, spi); | ||
776 | } | 774 | } |
777 | 775 | ||
778 | msg->actual_length += xfer->len; | 776 | msg->actual_length += xfer->len; |
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 32f7b55fce09..60cfae51c713 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c | |||
@@ -290,7 +290,7 @@ static int hspi_probe(struct platform_device *pdev) | |||
290 | } | 290 | } |
291 | 291 | ||
292 | clk = clk_get(NULL, "shyway_clk"); | 292 | clk = clk_get(NULL, "shyway_clk"); |
293 | if (!clk) { | 293 | if (IS_ERR(clk)) { |
294 | dev_err(&pdev->dev, "shyway_clk is required\n"); | 294 | dev_err(&pdev->dev, "shyway_clk is required\n"); |
295 | ret = -EINVAL; | 295 | ret = -EINVAL; |
296 | goto error0; | 296 | goto error0; |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index ab095acdb2a8..19ee901577da 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -824,6 +824,7 @@ static void of_register_spi_devices(struct spi_master *master) | |||
824 | struct spi_device *spi; | 824 | struct spi_device *spi; |
825 | struct device_node *nc; | 825 | struct device_node *nc; |
826 | const __be32 *prop; | 826 | const __be32 *prop; |
827 | char modalias[SPI_NAME_SIZE + 4]; | ||
827 | int rc; | 828 | int rc; |
828 | int len; | 829 | int len; |
829 | 830 | ||
@@ -887,7 +888,9 @@ static void of_register_spi_devices(struct spi_master *master) | |||
887 | spi->dev.of_node = nc; | 888 | spi->dev.of_node = nc; |
888 | 889 | ||
889 | /* Register the new device */ | 890 | /* Register the new device */ |
890 | request_module(spi->modalias); | 891 | snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX, |
892 | spi->modalias); | ||
893 | request_module(modalias); | ||
891 | rc = spi_add_device(spi); | 894 | rc = spi_add_device(spi); |
892 | if (rc) { | 895 | if (rc) { |
893 | dev_err(&master->dev, "spi_device register error %s\n", | 896 | dev_err(&master->dev, "spi_device register error %s\n", |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 0c96eb52c797..03310721712f 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
@@ -417,14 +417,16 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
417 | spin_unlock(&c->erase_completion_lock); | 417 | spin_unlock(&c->erase_completion_lock); |
418 | 418 | ||
419 | ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); | 419 | ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); |
420 | if (ret) | 420 | |
421 | return ret; | ||
422 | /* Just lock it again and continue. Nothing much can change because | 421 | /* Just lock it again and continue. Nothing much can change because |
423 | we hold c->alloc_sem anyway. In fact, it's not entirely clear why | 422 | we hold c->alloc_sem anyway. In fact, it's not entirely clear why |
424 | we hold c->erase_completion_lock in the majority of this function... | 423 | we hold c->erase_completion_lock in the majority of this function... |
425 | but that's a question for another (more caffeine-rich) day. */ | 424 | but that's a question for another (more caffeine-rich) day. */ |
426 | spin_lock(&c->erase_completion_lock); | 425 | spin_lock(&c->erase_completion_lock); |
427 | 426 | ||
427 | if (ret) | ||
428 | return ret; | ||
429 | |||
428 | waste = jeb->free_size; | 430 | waste = jeb->free_size; |
429 | jffs2_link_node_ref(c, jeb, | 431 | jffs2_link_node_ref(c, jeb, |
430 | (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, | 432 | (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, |
diff --git a/include/linux/asn1.h b/include/linux/asn1.h index 5c3f4e4b9a23..eed6982860ba 100644 --- a/include/linux/asn1.h +++ b/include/linux/asn1.h | |||
@@ -64,4 +64,6 @@ enum asn1_tag { | |||
64 | ASN1_LONG_TAG = 31 /* Long form tag */ | 64 | ASN1_LONG_TAG = 31 /* Long form tag */ |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #define ASN1_INDEFINITE_LENGTH 0x80 | ||
68 | |||
67 | #endif /* _LINUX_ASN1_H */ | 69 | #endif /* _LINUX_ASN1_H */ |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 93b1e091b1e9..e0ce311011c0 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -350,6 +350,7 @@ extern void bcma_core_set_clockmode(struct bcma_device *core, | |||
350 | enum bcma_clkmode clkmode); | 350 | enum bcma_clkmode clkmode); |
351 | extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, | 351 | extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, |
352 | bool on); | 352 | bool on); |
353 | extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset); | ||
353 | #define BCMA_DMA_TRANSLATION_MASK 0xC0000000 | 354 | #define BCMA_DMA_TRANSLATION_MASK 0xC0000000 |
354 | #define BCMA_DMA_TRANSLATION_NONE 0x00000000 | 355 | #define BCMA_DMA_TRANSLATION_NONE 0x00000000 |
355 | #define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */ | 356 | #define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */ |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index acb4f7bbbd32..f94bc83011ed 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -1188,14 +1188,25 @@ static inline int queue_discard_alignment(struct request_queue *q) | |||
1188 | 1188 | ||
1189 | static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector_t sector) | 1189 | static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector_t sector) |
1190 | { | 1190 | { |
1191 | sector_t alignment = sector << 9; | 1191 | unsigned int alignment, granularity, offset; |
1192 | alignment = sector_div(alignment, lim->discard_granularity); | ||
1193 | 1192 | ||
1194 | if (!lim->max_discard_sectors) | 1193 | if (!lim->max_discard_sectors) |
1195 | return 0; | 1194 | return 0; |
1196 | 1195 | ||
1197 | alignment = lim->discard_granularity + lim->discard_alignment - alignment; | 1196 | /* Why are these in bytes, not sectors? */ |
1198 | return sector_div(alignment, lim->discard_granularity); | 1197 | alignment = lim->discard_alignment >> 9; |
1198 | granularity = lim->discard_granularity >> 9; | ||
1199 | if (!granularity) | ||
1200 | return 0; | ||
1201 | |||
1202 | /* Offset of the partition start in 'granularity' sectors */ | ||
1203 | offset = sector_div(sector, granularity); | ||
1204 | |||
1205 | /* And why do we do this modulus *again* in blkdev_issue_discard()? */ | ||
1206 | offset = (granularity + alignment - offset) % granularity; | ||
1207 | |||
1208 | /* Turn it back into bytes, gaah */ | ||
1209 | return offset << 9; | ||
1199 | } | 1210 | } |
1200 | 1211 | ||
1201 | static inline int bdev_discard_alignment(struct block_device *bdev) | 1212 | static inline int bdev_discard_alignment(struct block_device *bdev) |
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 412bc6c2b023..662fd1b4c42a 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h | |||
@@ -31,6 +31,8 @@ | |||
31 | 31 | ||
32 | #define __linktime_error(message) __attribute__((__error__(message))) | 32 | #define __linktime_error(message) __attribute__((__error__(message))) |
33 | 33 | ||
34 | #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) | ||
35 | |||
34 | #if __GNUC_MINOR__ >= 5 | 36 | #if __GNUC_MINOR__ >= 5 |
35 | /* | 37 | /* |
36 | * Mark a position in code as unreachable. This can be used to | 38 | * Mark a position in code as unreachable. This can be used to |
@@ -63,3 +65,13 @@ | |||
63 | #define __compiletime_warning(message) __attribute__((warning(message))) | 65 | #define __compiletime_warning(message) __attribute__((warning(message))) |
64 | #define __compiletime_error(message) __attribute__((error(message))) | 66 | #define __compiletime_error(message) __attribute__((error(message))) |
65 | #endif | 67 | #endif |
68 | |||
69 | #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP | ||
70 | #if __GNUC_MINOR__ >= 4 | ||
71 | #define __HAVE_BUILTIN_BSWAP32__ | ||
72 | #define __HAVE_BUILTIN_BSWAP64__ | ||
73 | #endif | ||
74 | #if __GNUC_MINOR__ >= 8 || (defined(__powerpc__) && __GNUC_MINOR__ >= 6) | ||
75 | #define __HAVE_BUILTIN_BSWAP16__ | ||
76 | #endif | ||
77 | #endif | ||
diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h index d8e636e5607d..973ce10c40b6 100644 --- a/include/linux/compiler-intel.h +++ b/include/linux/compiler-intel.h | |||
@@ -29,3 +29,10 @@ | |||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define uninitialized_var(x) x | 31 | #define uninitialized_var(x) x |
32 | |||
33 | #ifndef __HAVE_BUILTIN_BSWAP16__ | ||
34 | /* icc has this, but it's called _bswap16 */ | ||
35 | #define __HAVE_BUILTIN_BSWAP16__ | ||
36 | #define __builtin_bswap16 _bswap16 | ||
37 | #endif | ||
38 | |||
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index b121554f1fe2..dd852b73b286 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -44,6 +44,10 @@ extern void __chk_io_ptr(const volatile void __iomem *); | |||
44 | # define __rcu | 44 | # define __rcu |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | /* Indirect macros required for expanded argument pasting, eg. __LINE__. */ | ||
48 | #define ___PASTE(a,b) a##b | ||
49 | #define __PASTE(a,b) ___PASTE(a,b) | ||
50 | |||
47 | #ifdef __KERNEL__ | 51 | #ifdef __KERNEL__ |
48 | 52 | ||
49 | #ifdef __GNUC__ | 53 | #ifdef __GNUC__ |
@@ -166,6 +170,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
166 | (typeof(ptr)) (__ptr + (off)); }) | 170 | (typeof(ptr)) (__ptr + (off)); }) |
167 | #endif | 171 | #endif |
168 | 172 | ||
173 | /* Not-quite-unique ID. */ | ||
174 | #ifndef __UNIQUE_ID | ||
175 | # define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__) | ||
176 | #endif | ||
177 | |||
169 | #endif /* __KERNEL__ */ | 178 | #endif /* __KERNEL__ */ |
170 | 179 | ||
171 | #endif /* __ASSEMBLY__ */ | 180 | #endif /* __ASSEMBLY__ */ |
diff --git a/include/linux/ima.h b/include/linux/ima.h index 2c7223d7e73b..86c361e947b9 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h | |||
@@ -18,6 +18,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm); | |||
18 | extern int ima_file_check(struct file *file, int mask); | 18 | extern int ima_file_check(struct file *file, int mask); |
19 | extern void ima_file_free(struct file *file); | 19 | extern void ima_file_free(struct file *file); |
20 | extern int ima_file_mmap(struct file *file, unsigned long prot); | 20 | extern int ima_file_mmap(struct file *file, unsigned long prot); |
21 | extern int ima_module_check(struct file *file); | ||
21 | 22 | ||
22 | #else | 23 | #else |
23 | static inline int ima_bprm_check(struct linux_binprm *bprm) | 24 | static inline int ima_bprm_check(struct linux_binprm *bprm) |
@@ -40,6 +41,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) | |||
40 | return 0; | 41 | return 0; |
41 | } | 42 | } |
42 | 43 | ||
44 | static inline int ima_module_check(struct file *file) | ||
45 | { | ||
46 | return 0; | ||
47 | } | ||
48 | |||
43 | #endif /* CONFIG_IMA_H */ | 49 | #endif /* CONFIG_IMA_H */ |
44 | 50 | ||
45 | #ifdef CONFIG_IMA_APPRAISE | 51 | #ifdef CONFIG_IMA_APPRAISE |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index d6a58065c09c..137b4198fc03 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -16,17 +16,15 @@ | |||
16 | /* Chosen so that structs with an unsigned long line up. */ | 16 | /* Chosen so that structs with an unsigned long line up. */ |
17 | #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) | 17 | #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) |
18 | 18 | ||
19 | #define ___module_cat(a,b) __mod_ ## a ## b | ||
20 | #define __module_cat(a,b) ___module_cat(a,b) | ||
21 | #ifdef MODULE | 19 | #ifdef MODULE |
22 | #define __MODULE_INFO(tag, name, info) \ | 20 | #define __MODULE_INFO(tag, name, info) \ |
23 | static const char __module_cat(name,__LINE__)[] \ | 21 | static const char __UNIQUE_ID(name)[] \ |
24 | __used __attribute__((section(".modinfo"), unused, aligned(1))) \ | 22 | __used __attribute__((section(".modinfo"), unused, aligned(1))) \ |
25 | = __stringify(tag) "=" info | 23 | = __stringify(tag) "=" info |
26 | #else /* !MODULE */ | 24 | #else /* !MODULE */ |
27 | /* This struct is here for syntactic coherency, it is not used */ | 25 | /* This struct is here for syntactic coherency, it is not used */ |
28 | #define __MODULE_INFO(tag, name, info) \ | 26 | #define __MODULE_INFO(tag, name, info) \ |
29 | struct __module_cat(name,__LINE__) {} | 27 | struct __UNIQUE_ID(name) {} |
30 | #endif | 28 | #endif |
31 | #define __MODULE_PARM_TYPE(name, _type) \ | 29 | #define __MODULE_PARM_TYPE(name, _type) \ |
32 | __MODULE_INFO(parmtype, name##type, #name ":" _type) | 30 | __MODULE_INFO(parmtype, name##type, #name ":" _type) |
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index ed270bd2e4df..4eb0a50d0c55 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/kref.h> | 24 | #include <linux/kref.h> |
25 | #include <linux/sysfs.h> | 25 | #include <linux/sysfs.h> |
26 | #include <linux/workqueue.h> | ||
26 | 27 | ||
27 | struct hd_geometry; | 28 | struct hd_geometry; |
28 | struct mtd_info; | 29 | struct mtd_info; |
@@ -43,7 +44,8 @@ struct mtd_blktrans_dev { | |||
43 | struct kref ref; | 44 | struct kref ref; |
44 | struct gendisk *disk; | 45 | struct gendisk *disk; |
45 | struct attribute_group *disk_attributes; | 46 | struct attribute_group *disk_attributes; |
46 | struct task_struct *thread; | 47 | struct workqueue_struct *wq; |
48 | struct work_struct work; | ||
47 | struct request_queue *rq; | 49 | struct request_queue *rq; |
48 | spinlock_t queue_lock; | 50 | spinlock_t queue_lock; |
49 | void *priv; | 51 | void *priv; |
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 0f6fea73a1f6..407d1e556c39 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h | |||
@@ -92,12 +92,26 @@ | |||
92 | * Others use readb/writeb | 92 | * Others use readb/writeb |
93 | */ | 93 | */ |
94 | #if defined(__arm__) | 94 | #if defined(__arm__) |
95 | #define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)))) | 95 | static inline u8 ReadDOC_(u32 __iomem *addr, unsigned long reg) |
96 | #define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0) | 96 | { |
97 | return __raw_readl(addr + reg); | ||
98 | } | ||
99 | static inline void WriteDOC_(u8 data, u32 __iomem *addr, unsigned long reg) | ||
100 | { | ||
101 | __raw_writel(data, addr + reg); | ||
102 | wmb(); | ||
103 | } | ||
97 | #define DOC_IOREMAP_LEN 0x8000 | 104 | #define DOC_IOREMAP_LEN 0x8000 |
98 | #elif defined(__ppc__) | 105 | #elif defined(__ppc__) |
99 | #define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)))) | 106 | static inline u8 ReadDOC_(u16 __iomem *addr, unsigned long reg) |
100 | #define WriteDOC_(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg)<<1)) = (__u16)d; wmb();} while(0) | 107 | { |
108 | return __raw_readw(addr + reg); | ||
109 | } | ||
110 | static inline void WriteDOC_(u8 data, u16 __iomem *addr, unsigned long reg) | ||
111 | { | ||
112 | __raw_writew(data, addr + reg); | ||
113 | wmb(); | ||
114 | } | ||
101 | #define DOC_IOREMAP_LEN 0x4000 | 115 | #define DOC_IOREMAP_LEN 0x4000 |
102 | #else | 116 | #else |
103 | #define ReadDOC_(adr, reg) readb((void __iomem *)(adr) + (reg)) | 117 | #define ReadDOC_(adr, reg) readb((void __iomem *)(adr) + (reg)) |
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index b20029221fb1..d6ed61ef451d 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h | |||
@@ -155,9 +155,6 @@ struct fsmc_nand_platform_data { | |||
155 | unsigned int width; | 155 | unsigned int width; |
156 | unsigned int bank; | 156 | unsigned int bank; |
157 | 157 | ||
158 | /* CLE, ALE offsets */ | ||
159 | unsigned int cle_off; | ||
160 | unsigned int ale_off; | ||
161 | enum access_mode mode; | 158 | enum access_mode mode; |
162 | 159 | ||
163 | void (*select_bank)(uint32_t bank, uint32_t busw); | 160 | void (*select_bank)(uint32_t bank, uint32_t busw); |
diff --git a/include/linux/mtd/gpmi-nand.h b/include/linux/mtd/gpmi-nand.h deleted file mode 100644 index ed3c4e09f3d1..000000000000 --- a/include/linux/mtd/gpmi-nand.h +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | */ | ||
18 | |||
19 | #ifndef __MACH_MXS_GPMI_NAND_H__ | ||
20 | #define __MACH_MXS_GPMI_NAND_H__ | ||
21 | |||
22 | /* The size of the resources is fixed. */ | ||
23 | #define GPMI_NAND_RES_SIZE 6 | ||
24 | |||
25 | /* Resource names for the GPMI NAND driver. */ | ||
26 | #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" | ||
27 | #define GPMI_NAND_GPMI_INTERRUPT_RES_NAME "GPMI NAND GPMI Interrupt" | ||
28 | #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch" | ||
29 | #define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch" | ||
30 | #define GPMI_NAND_DMA_CHANNELS_RES_NAME "GPMI NAND DMA Channels" | ||
31 | #define GPMI_NAND_DMA_INTERRUPT_RES_NAME "gpmi-dma" | ||
32 | |||
33 | /** | ||
34 | * struct gpmi_nand_platform_data - GPMI NAND driver platform data. | ||
35 | * | ||
36 | * This structure communicates platform-specific information to the GPMI NAND | ||
37 | * driver that can't be expressed as resources. | ||
38 | * | ||
39 | * @platform_init: A pointer to a function the driver will call to | ||
40 | * initialize the platform (e.g., set up the pin mux). | ||
41 | * @min_prop_delay_in_ns: Minimum propagation delay of GPMI signals to and | ||
42 | * from the NAND Flash device, in nanoseconds. | ||
43 | * @max_prop_delay_in_ns: Maximum propagation delay of GPMI signals to and | ||
44 | * from the NAND Flash device, in nanoseconds. | ||
45 | * @max_chip_count: The maximum number of chips for which the driver | ||
46 | * should configure the hardware. This value most | ||
47 | * likely reflects the number of pins that are | ||
48 | * connected to a NAND Flash device. If this is | ||
49 | * greater than the SoC hardware can support, the | ||
50 | * driver will print a message and fail to initialize. | ||
51 | * @partitions: An optional pointer to an array of partition | ||
52 | * descriptions. | ||
53 | * @partition_count: The number of elements in the partitions array. | ||
54 | */ | ||
55 | struct gpmi_nand_platform_data { | ||
56 | /* SoC hardware information. */ | ||
57 | int (*platform_init)(void); | ||
58 | |||
59 | /* NAND Flash information. */ | ||
60 | unsigned int min_prop_delay_in_ns; | ||
61 | unsigned int max_prop_delay_in_ns; | ||
62 | unsigned int max_chip_count; | ||
63 | |||
64 | /* Medium information. */ | ||
65 | struct mtd_partition *partitions; | ||
66 | unsigned partition_count; | ||
67 | }; | ||
68 | #endif | ||
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 3595a0236b0f..f6eb4332ac92 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h | |||
@@ -328,7 +328,7 @@ static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word | |||
328 | 328 | ||
329 | static inline map_word map_word_load(struct map_info *map, const void *ptr) | 329 | static inline map_word map_word_load(struct map_info *map, const void *ptr) |
330 | { | 330 | { |
331 | map_word r; | 331 | map_word r = {{0} }; |
332 | 332 | ||
333 | if (map_bankwidth_is_1(map)) | 333 | if (map_bankwidth_is_1(map)) |
334 | r.x[0] = *(unsigned char *)ptr; | 334 | r.x[0] = *(unsigned char *)ptr; |
@@ -391,7 +391,7 @@ static inline map_word map_word_ff(struct map_info *map) | |||
391 | 391 | ||
392 | static inline map_word inline_map_read(struct map_info *map, unsigned long ofs) | 392 | static inline map_word inline_map_read(struct map_info *map, unsigned long ofs) |
393 | { | 393 | { |
394 | map_word r; | 394 | map_word uninitialized_var(r); |
395 | 395 | ||
396 | if (map_bankwidth_is_1(map)) | 396 | if (map_bankwidth_is_1(map)) |
397 | r.x[0] = __raw_readb(map->virt + ofs); | 397 | r.x[0] = __raw_readb(map->virt + ofs); |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 81d61e704599..f9ac2897b86b 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -98,7 +98,7 @@ struct mtd_oob_ops { | |||
98 | }; | 98 | }; |
99 | 99 | ||
100 | #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 | 100 | #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 |
101 | #define MTD_MAX_ECCPOS_ENTRIES_LARGE 448 | 101 | #define MTD_MAX_ECCPOS_ENTRIES_LARGE 640 |
102 | /* | 102 | /* |
103 | * Internal ECC layout control structure. For historical reasons, there is a | 103 | * Internal ECC layout control structure. For historical reasons, there is a |
104 | * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained | 104 | * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 24e915957e4f..7ccb3c59ed60 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -219,6 +219,13 @@ typedef enum { | |||
219 | #define NAND_OWN_BUFFERS 0x00020000 | 219 | #define NAND_OWN_BUFFERS 0x00020000 |
220 | /* Chip may not exist, so silence any errors in scan */ | 220 | /* Chip may not exist, so silence any errors in scan */ |
221 | #define NAND_SCAN_SILENT_NODEV 0x00040000 | 221 | #define NAND_SCAN_SILENT_NODEV 0x00040000 |
222 | /* | ||
223 | * Autodetect nand buswidth with readid/onfi. | ||
224 | * This suppose the driver will configure the hardware in 8 bits mode | ||
225 | * when calling nand_scan_ident, and update its configuration | ||
226 | * before calling nand_scan_tail. | ||
227 | */ | ||
228 | #define NAND_BUSWIDTH_AUTO 0x00080000 | ||
222 | 229 | ||
223 | /* Options set by nand scan */ | 230 | /* Options set by nand scan */ |
224 | /* Nand scan has allocated controller struct */ | 231 | /* Nand scan has allocated controller struct */ |
@@ -471,8 +478,8 @@ struct nand_buffers { | |||
471 | * non 0 if ONFI supported. | 478 | * non 0 if ONFI supported. |
472 | * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is | 479 | * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is |
473 | * supported, 0 otherwise. | 480 | * supported, 0 otherwise. |
474 | * @onfi_set_features [REPLACEABLE] set the features for ONFI nand | 481 | * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand |
475 | * @onfi_get_features [REPLACEABLE] get the features for ONFI nand | 482 | * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand |
476 | * @ecclayout: [REPLACEABLE] the default ECC placement scheme | 483 | * @ecclayout: [REPLACEABLE] the default ECC placement scheme |
477 | * @bbt: [INTERN] bad block table pointer | 484 | * @bbt: [INTERN] bad block table pointer |
478 | * @bbt_td: [REPLACEABLE] bad block table descriptor for flash | 485 | * @bbt_td: [REPLACEABLE] bad block table descriptor for flash |
diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h index 01e4b15b280e..1c28f8879b1c 100644 --- a/include/linux/mtd/sh_flctl.h +++ b/include/linux/mtd/sh_flctl.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #ifndef __SH_FLCTL_H__ | 20 | #ifndef __SH_FLCTL_H__ |
21 | #define __SH_FLCTL_H__ | 21 | #define __SH_FLCTL_H__ |
22 | 22 | ||
23 | #include <linux/completion.h> | ||
23 | #include <linux/mtd/mtd.h> | 24 | #include <linux/mtd/mtd.h> |
24 | #include <linux/mtd/nand.h> | 25 | #include <linux/mtd/nand.h> |
25 | #include <linux/mtd/partitions.h> | 26 | #include <linux/mtd/partitions.h> |
@@ -107,6 +108,7 @@ | |||
107 | #define ESTERINTE (0x1 << 24) /* ECC error interrupt enable */ | 108 | #define ESTERINTE (0x1 << 24) /* ECC error interrupt enable */ |
108 | #define AC1CLR (0x1 << 19) /* ECC FIFO clear */ | 109 | #define AC1CLR (0x1 << 19) /* ECC FIFO clear */ |
109 | #define AC0CLR (0x1 << 18) /* Data FIFO clear */ | 110 | #define AC0CLR (0x1 << 18) /* Data FIFO clear */ |
111 | #define DREQ0EN (0x1 << 16) /* FLDTFIFODMA Request Enable */ | ||
110 | #define ECERB (0x1 << 9) /* ECC error */ | 112 | #define ECERB (0x1 << 9) /* ECC error */ |
111 | #define STERB (0x1 << 8) /* Status error */ | 113 | #define STERB (0x1 << 8) /* Status error */ |
112 | #define STERINTE (0x1 << 4) /* Status error enable */ | 114 | #define STERINTE (0x1 << 4) /* Status error enable */ |
@@ -138,6 +140,8 @@ enum flctl_ecc_res_t { | |||
138 | FL_TIMEOUT | 140 | FL_TIMEOUT |
139 | }; | 141 | }; |
140 | 142 | ||
143 | struct dma_chan; | ||
144 | |||
141 | struct sh_flctl { | 145 | struct sh_flctl { |
142 | struct mtd_info mtd; | 146 | struct mtd_info mtd; |
143 | struct nand_chip chip; | 147 | struct nand_chip chip; |
@@ -147,7 +151,7 @@ struct sh_flctl { | |||
147 | 151 | ||
148 | uint8_t done_buff[2048 + 64]; /* max size 2048 + 64 */ | 152 | uint8_t done_buff[2048 + 64]; /* max size 2048 + 64 */ |
149 | int read_bytes; | 153 | int read_bytes; |
150 | int index; | 154 | unsigned int index; |
151 | int seqin_column; /* column in SEQIN cmd */ | 155 | int seqin_column; /* column in SEQIN cmd */ |
152 | int seqin_page_addr; /* page_addr in SEQIN cmd */ | 156 | int seqin_page_addr; /* page_addr in SEQIN cmd */ |
153 | uint32_t seqin_read_cmd; /* read cmd in SEQIN cmd */ | 157 | uint32_t seqin_read_cmd; /* read cmd in SEQIN cmd */ |
@@ -161,6 +165,11 @@ struct sh_flctl { | |||
161 | unsigned hwecc:1; /* Hardware ECC (0 = disabled, 1 = enabled) */ | 165 | unsigned hwecc:1; /* Hardware ECC (0 = disabled, 1 = enabled) */ |
162 | unsigned holden:1; /* Hardware has FLHOLDCR and HOLDEN is set */ | 166 | unsigned holden:1; /* Hardware has FLHOLDCR and HOLDEN is set */ |
163 | unsigned qos_request:1; /* QoS request to prevent deep power shutdown */ | 167 | unsigned qos_request:1; /* QoS request to prevent deep power shutdown */ |
168 | |||
169 | /* DMA related objects */ | ||
170 | struct dma_chan *chan_fifo0_rx; | ||
171 | struct dma_chan *chan_fifo0_tx; | ||
172 | struct completion dma_complete; | ||
164 | }; | 173 | }; |
165 | 174 | ||
166 | struct sh_flctl_platform_data { | 175 | struct sh_flctl_platform_data { |
@@ -170,6 +179,9 @@ struct sh_flctl_platform_data { | |||
170 | 179 | ||
171 | unsigned has_hwecc:1; | 180 | unsigned has_hwecc:1; |
172 | unsigned use_holden:1; | 181 | unsigned use_holden:1; |
182 | |||
183 | unsigned int slave_id_fifo0_tx; | ||
184 | unsigned int slave_id_fifo0_rx; | ||
173 | }; | 185 | }; |
174 | 186 | ||
175 | static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo) | 187 | static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo) |
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index b47d2040c9f2..3863a4dbdf18 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h | |||
@@ -100,6 +100,7 @@ extern int of_platform_populate(struct device_node *root, | |||
100 | 100 | ||
101 | #if !defined(CONFIG_OF_ADDRESS) | 101 | #if !defined(CONFIG_OF_ADDRESS) |
102 | struct of_dev_auxdata; | 102 | struct of_dev_auxdata; |
103 | struct device; | ||
103 | static inline int of_platform_populate(struct device_node *root, | 104 | static inline int of_platform_populate(struct device_node *root, |
104 | const struct of_device_id *matches, | 105 | const struct of_device_id *matches, |
105 | const struct of_dev_auxdata *lookup, | 106 | const struct of_dev_auxdata *lookup, |
diff --git a/include/linux/platform_data/mtd-nomadik-nand.h b/include/linux/platform_data/mtd-nomadik-nand.h deleted file mode 100644 index c3c8254c22a5..000000000000 --- a/include/linux/platform_data/mtd-nomadik-nand.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | #ifndef __ASM_ARCH_NAND_H | ||
2 | #define __ASM_ARCH_NAND_H | ||
3 | |||
4 | struct nomadik_nand_platform_data { | ||
5 | struct mtd_partition *parts; | ||
6 | int nparts; | ||
7 | int options; | ||
8 | int (*init) (void); | ||
9 | int (*exit) (void); | ||
10 | }; | ||
11 | |||
12 | #define NAND_IO_DATA 0x40000000 | ||
13 | #define NAND_IO_CMD 0x40800000 | ||
14 | #define NAND_IO_ADDR 0x41000000 | ||
15 | |||
16 | #endif /* __ASM_ARCH_NAND_H */ | ||
diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 112b31436848..6d661f32e0e4 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h | |||
@@ -171,6 +171,9 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, | |||
171 | unsigned int index, | 171 | unsigned int index, |
172 | const char *label); | 172 | const char *label); |
173 | 173 | ||
174 | struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc, | ||
175 | const struct of_phandle_args *args); | ||
176 | |||
174 | struct pwm_device *pwm_get(struct device *dev, const char *consumer); | 177 | struct pwm_device *pwm_get(struct device *dev, const char *consumer); |
175 | void pwm_put(struct pwm_device *pwm); | 178 | void pwm_put(struct pwm_device *pwm); |
176 | 179 | ||
diff --git a/include/linux/security.h b/include/linux/security.h index 05e88bdcf7d9..0f6afc657f77 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -694,6 +694,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
694 | * userspace to load a kernel module with the given name. | 694 | * userspace to load a kernel module with the given name. |
695 | * @kmod_name name of the module requested by the kernel | 695 | * @kmod_name name of the module requested by the kernel |
696 | * Return 0 if successful. | 696 | * Return 0 if successful. |
697 | * @kernel_module_from_file: | ||
698 | * Load a kernel module from userspace. | ||
699 | * @file contains the file structure pointing to the file containing | ||
700 | * the kernel module to load. If the module is being loaded from a blob, | ||
701 | * this argument will be NULL. | ||
702 | * Return 0 if permission is granted. | ||
697 | * @task_fix_setuid: | 703 | * @task_fix_setuid: |
698 | * Update the module's state after setting one or more of the user | 704 | * Update the module's state after setting one or more of the user |
699 | * identity attributes of the current process. The @flags parameter | 705 | * identity attributes of the current process. The @flags parameter |
@@ -1508,6 +1514,7 @@ struct security_operations { | |||
1508 | int (*kernel_act_as)(struct cred *new, u32 secid); | 1514 | int (*kernel_act_as)(struct cred *new, u32 secid); |
1509 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); | 1515 | int (*kernel_create_files_as)(struct cred *new, struct inode *inode); |
1510 | int (*kernel_module_request)(char *kmod_name); | 1516 | int (*kernel_module_request)(char *kmod_name); |
1517 | int (*kernel_module_from_file)(struct file *file); | ||
1511 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, | 1518 | int (*task_fix_setuid) (struct cred *new, const struct cred *old, |
1512 | int flags); | 1519 | int flags); |
1513 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); | 1520 | int (*task_setpgid) (struct task_struct *p, pid_t pgid); |
@@ -1765,6 +1772,7 @@ void security_transfer_creds(struct cred *new, const struct cred *old); | |||
1765 | int security_kernel_act_as(struct cred *new, u32 secid); | 1772 | int security_kernel_act_as(struct cred *new, u32 secid); |
1766 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); | 1773 | int security_kernel_create_files_as(struct cred *new, struct inode *inode); |
1767 | int security_kernel_module_request(char *kmod_name); | 1774 | int security_kernel_module_request(char *kmod_name); |
1775 | int security_kernel_module_from_file(struct file *file); | ||
1768 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 1776 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
1769 | int flags); | 1777 | int flags); |
1770 | int security_task_setpgid(struct task_struct *p, pid_t pgid); | 1778 | int security_task_setpgid(struct task_struct *p, pid_t pgid); |
@@ -2278,6 +2286,11 @@ static inline int security_kernel_module_request(char *kmod_name) | |||
2278 | return 0; | 2286 | return 0; |
2279 | } | 2287 | } |
2280 | 2288 | ||
2289 | static inline int security_kernel_module_from_file(struct file *file) | ||
2290 | { | ||
2291 | return 0; | ||
2292 | } | ||
2293 | |||
2281 | static inline int security_task_fix_setuid(struct cred *new, | 2294 | static inline int security_task_fix_setuid(struct cred *new, |
2282 | const struct cred *old, | 2295 | const struct cred *old, |
2283 | int flags) | 2296 | int flags) |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 36c3b07c5119..6caee34bf8a2 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -880,4 +880,5 @@ asmlinkage long sys_process_vm_writev(pid_t pid, | |||
880 | 880 | ||
881 | asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, | 881 | asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, |
882 | unsigned long idx1, unsigned long idx2); | 882 | unsigned long idx1, unsigned long idx2); |
883 | asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); | ||
883 | #endif | 884 | #endif |
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 6e595ba545f4..2c531f478410 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h | |||
@@ -690,9 +690,11 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ | |||
690 | compat_sys_process_vm_writev) | 690 | compat_sys_process_vm_writev) |
691 | #define __NR_kcmp 272 | 691 | #define __NR_kcmp 272 |
692 | __SYSCALL(__NR_kcmp, sys_kcmp) | 692 | __SYSCALL(__NR_kcmp, sys_kcmp) |
693 | #define __NR_finit_module 273 | ||
694 | __SYSCALL(__NR_finit_module, sys_finit_module) | ||
693 | 695 | ||
694 | #undef __NR_syscalls | 696 | #undef __NR_syscalls |
695 | #define __NR_syscalls 273 | 697 | #define __NR_syscalls 274 |
696 | 698 | ||
697 | /* | 699 | /* |
698 | * All syscalls below here should go away really, | 700 | * All syscalls below here should go away really, |
diff --git a/include/uapi/linux/module.h b/include/uapi/linux/module.h new file mode 100644 index 000000000000..38da4258b12f --- /dev/null +++ b/include/uapi/linux/module.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _UAPI_LINUX_MODULE_H | ||
2 | #define _UAPI_LINUX_MODULE_H | ||
3 | |||
4 | /* Flags for sys_finit_module: */ | ||
5 | #define MODULE_INIT_IGNORE_MODVERSIONS 1 | ||
6 | #define MODULE_INIT_IGNORE_VERMAGIC 2 | ||
7 | |||
8 | #endif /* _UAPI_LINUX_MODULE_H */ | ||
diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h index e811474724c2..0e011eb91b5d 100644 --- a/include/uapi/linux/swab.h +++ b/include/uapi/linux/swab.h | |||
@@ -45,7 +45,9 @@ | |||
45 | 45 | ||
46 | static inline __attribute_const__ __u16 __fswab16(__u16 val) | 46 | static inline __attribute_const__ __u16 __fswab16(__u16 val) |
47 | { | 47 | { |
48 | #ifdef __arch_swab16 | 48 | #ifdef __HAVE_BUILTIN_BSWAP16__ |
49 | return __builtin_bswap16(val); | ||
50 | #elif defined (__arch_swab16) | ||
49 | return __arch_swab16(val); | 51 | return __arch_swab16(val); |
50 | #else | 52 | #else |
51 | return ___constant_swab16(val); | 53 | return ___constant_swab16(val); |
@@ -54,7 +56,9 @@ static inline __attribute_const__ __u16 __fswab16(__u16 val) | |||
54 | 56 | ||
55 | static inline __attribute_const__ __u32 __fswab32(__u32 val) | 57 | static inline __attribute_const__ __u32 __fswab32(__u32 val) |
56 | { | 58 | { |
57 | #ifdef __arch_swab32 | 59 | #ifdef __HAVE_BUILTIN_BSWAP32__ |
60 | return __builtin_bswap32(val); | ||
61 | #elif defined(__arch_swab32) | ||
58 | return __arch_swab32(val); | 62 | return __arch_swab32(val); |
59 | #else | 63 | #else |
60 | return ___constant_swab32(val); | 64 | return ___constant_swab32(val); |
@@ -63,7 +67,9 @@ static inline __attribute_const__ __u32 __fswab32(__u32 val) | |||
63 | 67 | ||
64 | static inline __attribute_const__ __u64 __fswab64(__u64 val) | 68 | static inline __attribute_const__ __u64 __fswab64(__u64 val) |
65 | { | 69 | { |
66 | #ifdef __arch_swab64 | 70 | #ifdef __HAVE_BUILTIN_BSWAP64__ |
71 | return __builtin_bswap64(val); | ||
72 | #elif defined (__arch_swab64) | ||
67 | return __arch_swab64(val); | 73 | return __arch_swab64(val); |
68 | #elif defined(__SWAB_64_THRU_32__) | 74 | #elif defined(__SWAB_64_THRU_32__) |
69 | __u32 h = val >> 32; | 75 | __u32 h = val >> 32; |
diff --git a/kernel/Makefile b/kernel/Makefile index ac0d533eb7de..6c072b6da239 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -54,7 +54,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o | |||
54 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o | 54 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o |
55 | obj-$(CONFIG_UID16) += uid16.o | 55 | obj-$(CONFIG_UID16) += uid16.o |
56 | obj-$(CONFIG_MODULES) += module.o | 56 | obj-$(CONFIG_MODULES) += module.o |
57 | obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o | 57 | obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o |
58 | obj-$(CONFIG_KALLSYMS) += kallsyms.o | 58 | obj-$(CONFIG_KALLSYMS) += kallsyms.o |
59 | obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o | 59 | obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o |
60 | obj-$(CONFIG_KEXEC) += kexec.o | 60 | obj-$(CONFIG_KEXEC) += kexec.o |
@@ -137,10 +137,14 @@ ifeq ($(CONFIG_MODULE_SIG),y) | |||
137 | # | 137 | # |
138 | # Pull the signing certificate and any extra certificates into the kernel | 138 | # Pull the signing certificate and any extra certificates into the kernel |
139 | # | 139 | # |
140 | |||
141 | quiet_cmd_touch = TOUCH $@ | ||
142 | cmd_touch = touch $@ | ||
143 | |||
140 | extra_certificates: | 144 | extra_certificates: |
141 | touch $@ | 145 | $(call cmd,touch) |
142 | 146 | ||
143 | kernel/modsign_pubkey.o: signing_key.x509 extra_certificates | 147 | kernel/modsign_certificate.o: signing_key.x509 extra_certificates |
144 | 148 | ||
145 | ############################################################################### | 149 | ############################################################################### |
146 | # | 150 | # |
diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S new file mode 100644 index 000000000000..246b4c6e6135 --- /dev/null +++ b/kernel/modsign_certificate.S | |||
@@ -0,0 +1,19 @@ | |||
1 | /* SYMBOL_PREFIX defined on commandline from CONFIG_SYMBOL_PREFIX */ | ||
2 | #ifndef SYMBOL_PREFIX | ||
3 | #define ASM_SYMBOL(sym) sym | ||
4 | #else | ||
5 | #define PASTE2(x,y) x##y | ||
6 | #define PASTE(x,y) PASTE2(x,y) | ||
7 | #define ASM_SYMBOL(sym) PASTE(SYMBOL_PREFIX, sym) | ||
8 | #endif | ||
9 | |||
10 | #define GLOBAL(name) \ | ||
11 | .globl ASM_SYMBOL(name); \ | ||
12 | ASM_SYMBOL(name): | ||
13 | |||
14 | .section ".init.data","aw" | ||
15 | |||
16 | GLOBAL(modsign_certificate_list) | ||
17 | .incbin "signing_key.x509" | ||
18 | .incbin "extra_certificates" | ||
19 | GLOBAL(modsign_certificate_list_end) | ||
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c index 767e559dfb10..045504fffbb2 100644 --- a/kernel/modsign_pubkey.c +++ b/kernel/modsign_pubkey.c | |||
@@ -20,12 +20,6 @@ struct key *modsign_keyring; | |||
20 | 20 | ||
21 | extern __initdata const u8 modsign_certificate_list[]; | 21 | extern __initdata const u8 modsign_certificate_list[]; |
22 | extern __initdata const u8 modsign_certificate_list_end[]; | 22 | extern __initdata const u8 modsign_certificate_list_end[]; |
23 | asm(".section .init.data,\"aw\"\n" | ||
24 | SYMBOL_PREFIX "modsign_certificate_list:\n" | ||
25 | ".incbin \"signing_key.x509\"\n" | ||
26 | ".incbin \"extra_certificates\"\n" | ||
27 | SYMBOL_PREFIX "modsign_certificate_list_end:" | ||
28 | ); | ||
29 | 23 | ||
30 | /* | 24 | /* |
31 | * We need to make sure ccache doesn't cache the .o file as it doesn't notice | 25 | * We need to make sure ccache doesn't cache the .o file as it doesn't notice |
diff --git a/kernel/module.c b/kernel/module.c index 808bd62e1723..250092c1d57d 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/ftrace_event.h> | 21 | #include <linux/ftrace_event.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/kallsyms.h> | 23 | #include <linux/kallsyms.h> |
24 | #include <linux/file.h> | ||
24 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
25 | #include <linux/sysfs.h> | 26 | #include <linux/sysfs.h> |
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
@@ -28,6 +29,7 @@ | |||
28 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
29 | #include <linux/elf.h> | 30 | #include <linux/elf.h> |
30 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
32 | #include <linux/security.h> | ||
31 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
32 | #include <linux/syscalls.h> | 34 | #include <linux/syscalls.h> |
33 | #include <linux/fcntl.h> | 35 | #include <linux/fcntl.h> |
@@ -59,6 +61,7 @@ | |||
59 | #include <linux/pfn.h> | 61 | #include <linux/pfn.h> |
60 | #include <linux/bsearch.h> | 62 | #include <linux/bsearch.h> |
61 | #include <linux/fips.h> | 63 | #include <linux/fips.h> |
64 | #include <uapi/linux/module.h> | ||
62 | #include "module-internal.h" | 65 | #include "module-internal.h" |
63 | 66 | ||
64 | #define CREATE_TRACE_POINTS | 67 | #define CREATE_TRACE_POINTS |
@@ -2279,7 +2282,7 @@ static void layout_symtab(struct module *mod, struct load_info *info) | |||
2279 | Elf_Shdr *symsect = info->sechdrs + info->index.sym; | 2282 | Elf_Shdr *symsect = info->sechdrs + info->index.sym; |
2280 | Elf_Shdr *strsect = info->sechdrs + info->index.str; | 2283 | Elf_Shdr *strsect = info->sechdrs + info->index.str; |
2281 | const Elf_Sym *src; | 2284 | const Elf_Sym *src; |
2282 | unsigned int i, nsrc, ndst, strtab_size; | 2285 | unsigned int i, nsrc, ndst, strtab_size = 0; |
2283 | 2286 | ||
2284 | /* Put symbol section at end of init part of module. */ | 2287 | /* Put symbol section at end of init part of module. */ |
2285 | symsect->sh_flags |= SHF_ALLOC; | 2288 | symsect->sh_flags |= SHF_ALLOC; |
@@ -2290,9 +2293,6 @@ static void layout_symtab(struct module *mod, struct load_info *info) | |||
2290 | src = (void *)info->hdr + symsect->sh_offset; | 2293 | src = (void *)info->hdr + symsect->sh_offset; |
2291 | nsrc = symsect->sh_size / sizeof(*src); | 2294 | nsrc = symsect->sh_size / sizeof(*src); |
2292 | 2295 | ||
2293 | /* strtab always starts with a nul, so offset 0 is the empty string. */ | ||
2294 | strtab_size = 1; | ||
2295 | |||
2296 | /* Compute total space required for the core symbols' strtab. */ | 2296 | /* Compute total space required for the core symbols' strtab. */ |
2297 | for (ndst = i = 0; i < nsrc; i++) { | 2297 | for (ndst = i = 0; i < nsrc; i++) { |
2298 | if (i == 0 || | 2298 | if (i == 0 || |
@@ -2334,7 +2334,6 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) | |||
2334 | mod->core_symtab = dst = mod->module_core + info->symoffs; | 2334 | mod->core_symtab = dst = mod->module_core + info->symoffs; |
2335 | mod->core_strtab = s = mod->module_core + info->stroffs; | 2335 | mod->core_strtab = s = mod->module_core + info->stroffs; |
2336 | src = mod->symtab; | 2336 | src = mod->symtab; |
2337 | *s++ = 0; | ||
2338 | for (ndst = i = 0; i < mod->num_symtab; i++) { | 2337 | for (ndst = i = 0; i < mod->num_symtab; i++) { |
2339 | if (i == 0 || | 2338 | if (i == 0 || |
2340 | is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { | 2339 | is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { |
@@ -2375,7 +2374,7 @@ static void dynamic_debug_remove(struct _ddebug *debug) | |||
2375 | 2374 | ||
2376 | void * __weak module_alloc(unsigned long size) | 2375 | void * __weak module_alloc(unsigned long size) |
2377 | { | 2376 | { |
2378 | return size == 0 ? NULL : vmalloc_exec(size); | 2377 | return vmalloc_exec(size); |
2379 | } | 2378 | } |
2380 | 2379 | ||
2381 | static void *module_alloc_update_bounds(unsigned long size) | 2380 | static void *module_alloc_update_bounds(unsigned long size) |
@@ -2422,18 +2421,17 @@ static inline void kmemleak_load_module(const struct module *mod, | |||
2422 | #endif | 2421 | #endif |
2423 | 2422 | ||
2424 | #ifdef CONFIG_MODULE_SIG | 2423 | #ifdef CONFIG_MODULE_SIG |
2425 | static int module_sig_check(struct load_info *info, | 2424 | static int module_sig_check(struct load_info *info) |
2426 | const void *mod, unsigned long *_len) | ||
2427 | { | 2425 | { |
2428 | int err = -ENOKEY; | 2426 | int err = -ENOKEY; |
2429 | unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; | 2427 | const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; |
2430 | unsigned long len = *_len; | 2428 | const void *mod = info->hdr; |
2431 | 2429 | ||
2432 | if (len > markerlen && | 2430 | if (info->len > markerlen && |
2433 | memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { | 2431 | memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { |
2434 | /* We truncate the module to discard the signature */ | 2432 | /* We truncate the module to discard the signature */ |
2435 | *_len -= markerlen; | 2433 | info->len -= markerlen; |
2436 | err = mod_verify_sig(mod, _len); | 2434 | err = mod_verify_sig(mod, &info->len); |
2437 | } | 2435 | } |
2438 | 2436 | ||
2439 | if (!err) { | 2437 | if (!err) { |
@@ -2451,59 +2449,107 @@ static int module_sig_check(struct load_info *info, | |||
2451 | return err; | 2449 | return err; |
2452 | } | 2450 | } |
2453 | #else /* !CONFIG_MODULE_SIG */ | 2451 | #else /* !CONFIG_MODULE_SIG */ |
2454 | static int module_sig_check(struct load_info *info, | 2452 | static int module_sig_check(struct load_info *info) |
2455 | void *mod, unsigned long *len) | ||
2456 | { | 2453 | { |
2457 | return 0; | 2454 | return 0; |
2458 | } | 2455 | } |
2459 | #endif /* !CONFIG_MODULE_SIG */ | 2456 | #endif /* !CONFIG_MODULE_SIG */ |
2460 | 2457 | ||
2461 | /* Sets info->hdr, info->len and info->sig_ok. */ | 2458 | /* Sanity checks against invalid binaries, wrong arch, weird elf version. */ |
2462 | static int copy_and_check(struct load_info *info, | 2459 | static int elf_header_check(struct load_info *info) |
2463 | const void __user *umod, unsigned long len, | 2460 | { |
2464 | const char __user *uargs) | 2461 | if (info->len < sizeof(*(info->hdr))) |
2462 | return -ENOEXEC; | ||
2463 | |||
2464 | if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0 | ||
2465 | || info->hdr->e_type != ET_REL | ||
2466 | || !elf_check_arch(info->hdr) | ||
2467 | || info->hdr->e_shentsize != sizeof(Elf_Shdr)) | ||
2468 | return -ENOEXEC; | ||
2469 | |||
2470 | if (info->hdr->e_shoff >= info->len | ||
2471 | || (info->hdr->e_shnum * sizeof(Elf_Shdr) > | ||
2472 | info->len - info->hdr->e_shoff)) | ||
2473 | return -ENOEXEC; | ||
2474 | |||
2475 | return 0; | ||
2476 | } | ||
2477 | |||
2478 | /* Sets info->hdr and info->len. */ | ||
2479 | static int copy_module_from_user(const void __user *umod, unsigned long len, | ||
2480 | struct load_info *info) | ||
2465 | { | 2481 | { |
2466 | int err; | 2482 | int err; |
2467 | Elf_Ehdr *hdr; | ||
2468 | 2483 | ||
2469 | if (len < sizeof(*hdr)) | 2484 | info->len = len; |
2485 | if (info->len < sizeof(*(info->hdr))) | ||
2470 | return -ENOEXEC; | 2486 | return -ENOEXEC; |
2471 | 2487 | ||
2488 | err = security_kernel_module_from_file(NULL); | ||
2489 | if (err) | ||
2490 | return err; | ||
2491 | |||
2472 | /* Suck in entire file: we'll want most of it. */ | 2492 | /* Suck in entire file: we'll want most of it. */ |
2473 | if ((hdr = vmalloc(len)) == NULL) | 2493 | info->hdr = vmalloc(info->len); |
2494 | if (!info->hdr) | ||
2474 | return -ENOMEM; | 2495 | return -ENOMEM; |
2475 | 2496 | ||
2476 | if (copy_from_user(hdr, umod, len) != 0) { | 2497 | if (copy_from_user(info->hdr, umod, info->len) != 0) { |
2477 | err = -EFAULT; | 2498 | vfree(info->hdr); |
2478 | goto free_hdr; | 2499 | return -EFAULT; |
2479 | } | 2500 | } |
2480 | 2501 | ||
2481 | err = module_sig_check(info, hdr, &len); | 2502 | return 0; |
2503 | } | ||
2504 | |||
2505 | /* Sets info->hdr and info->len. */ | ||
2506 | static int copy_module_from_fd(int fd, struct load_info *info) | ||
2507 | { | ||
2508 | struct file *file; | ||
2509 | int err; | ||
2510 | struct kstat stat; | ||
2511 | loff_t pos; | ||
2512 | ssize_t bytes = 0; | ||
2513 | |||
2514 | file = fget(fd); | ||
2515 | if (!file) | ||
2516 | return -ENOEXEC; | ||
2517 | |||
2518 | err = security_kernel_module_from_file(file); | ||
2482 | if (err) | 2519 | if (err) |
2483 | goto free_hdr; | 2520 | goto out; |
2484 | 2521 | ||
2485 | /* Sanity checks against insmoding binaries or wrong arch, | 2522 | err = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); |
2486 | weird elf version */ | 2523 | if (err) |
2487 | if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 | 2524 | goto out; |
2488 | || hdr->e_type != ET_REL | ||
2489 | || !elf_check_arch(hdr) | ||
2490 | || hdr->e_shentsize != sizeof(Elf_Shdr)) { | ||
2491 | err = -ENOEXEC; | ||
2492 | goto free_hdr; | ||
2493 | } | ||
2494 | 2525 | ||
2495 | if (hdr->e_shoff >= len || | 2526 | if (stat.size > INT_MAX) { |
2496 | hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) { | 2527 | err = -EFBIG; |
2497 | err = -ENOEXEC; | 2528 | goto out; |
2498 | goto free_hdr; | 2529 | } |
2530 | info->hdr = vmalloc(stat.size); | ||
2531 | if (!info->hdr) { | ||
2532 | err = -ENOMEM; | ||
2533 | goto out; | ||
2499 | } | 2534 | } |
2500 | 2535 | ||
2501 | info->hdr = hdr; | 2536 | pos = 0; |
2502 | info->len = len; | 2537 | while (pos < stat.size) { |
2503 | return 0; | 2538 | bytes = kernel_read(file, pos, (char *)(info->hdr) + pos, |
2539 | stat.size - pos); | ||
2540 | if (bytes < 0) { | ||
2541 | vfree(info->hdr); | ||
2542 | err = bytes; | ||
2543 | goto out; | ||
2544 | } | ||
2545 | if (bytes == 0) | ||
2546 | break; | ||
2547 | pos += bytes; | ||
2548 | } | ||
2549 | info->len = pos; | ||
2504 | 2550 | ||
2505 | free_hdr: | 2551 | out: |
2506 | vfree(hdr); | 2552 | fput(file); |
2507 | return err; | 2553 | return err; |
2508 | } | 2554 | } |
2509 | 2555 | ||
@@ -2512,7 +2558,7 @@ static void free_copy(struct load_info *info) | |||
2512 | vfree(info->hdr); | 2558 | vfree(info->hdr); |
2513 | } | 2559 | } |
2514 | 2560 | ||
2515 | static int rewrite_section_headers(struct load_info *info) | 2561 | static int rewrite_section_headers(struct load_info *info, int flags) |
2516 | { | 2562 | { |
2517 | unsigned int i; | 2563 | unsigned int i; |
2518 | 2564 | ||
@@ -2540,7 +2586,10 @@ static int rewrite_section_headers(struct load_info *info) | |||
2540 | } | 2586 | } |
2541 | 2587 | ||
2542 | /* Track but don't keep modinfo and version sections. */ | 2588 | /* Track but don't keep modinfo and version sections. */ |
2543 | info->index.vers = find_sec(info, "__versions"); | 2589 | if (flags & MODULE_INIT_IGNORE_MODVERSIONS) |
2590 | info->index.vers = 0; /* Pretend no __versions section! */ | ||
2591 | else | ||
2592 | info->index.vers = find_sec(info, "__versions"); | ||
2544 | info->index.info = find_sec(info, ".modinfo"); | 2593 | info->index.info = find_sec(info, ".modinfo"); |
2545 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2594 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; |
2546 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2595 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; |
@@ -2555,7 +2604,7 @@ static int rewrite_section_headers(struct load_info *info) | |||
2555 | * Return the temporary module pointer (we'll replace it with the final | 2604 | * Return the temporary module pointer (we'll replace it with the final |
2556 | * one when we move the module sections around). | 2605 | * one when we move the module sections around). |
2557 | */ | 2606 | */ |
2558 | static struct module *setup_load_info(struct load_info *info) | 2607 | static struct module *setup_load_info(struct load_info *info, int flags) |
2559 | { | 2608 | { |
2560 | unsigned int i; | 2609 | unsigned int i; |
2561 | int err; | 2610 | int err; |
@@ -2566,7 +2615,7 @@ static struct module *setup_load_info(struct load_info *info) | |||
2566 | info->secstrings = (void *)info->hdr | 2615 | info->secstrings = (void *)info->hdr |
2567 | + info->sechdrs[info->hdr->e_shstrndx].sh_offset; | 2616 | + info->sechdrs[info->hdr->e_shstrndx].sh_offset; |
2568 | 2617 | ||
2569 | err = rewrite_section_headers(info); | 2618 | err = rewrite_section_headers(info, flags); |
2570 | if (err) | 2619 | if (err) |
2571 | return ERR_PTR(err); | 2620 | return ERR_PTR(err); |
2572 | 2621 | ||
@@ -2604,11 +2653,14 @@ static struct module *setup_load_info(struct load_info *info) | |||
2604 | return mod; | 2653 | return mod; |
2605 | } | 2654 | } |
2606 | 2655 | ||
2607 | static int check_modinfo(struct module *mod, struct load_info *info) | 2656 | static int check_modinfo(struct module *mod, struct load_info *info, int flags) |
2608 | { | 2657 | { |
2609 | const char *modmagic = get_modinfo(info, "vermagic"); | 2658 | const char *modmagic = get_modinfo(info, "vermagic"); |
2610 | int err; | 2659 | int err; |
2611 | 2660 | ||
2661 | if (flags & MODULE_INIT_IGNORE_VERMAGIC) | ||
2662 | modmagic = NULL; | ||
2663 | |||
2612 | /* This is allowed: modprobe --force will invalidate it. */ | 2664 | /* This is allowed: modprobe --force will invalidate it. */ |
2613 | if (!modmagic) { | 2665 | if (!modmagic) { |
2614 | err = try_to_force_load(mod, "bad vermagic"); | 2666 | err = try_to_force_load(mod, "bad vermagic"); |
@@ -2738,20 +2790,23 @@ static int move_module(struct module *mod, struct load_info *info) | |||
2738 | memset(ptr, 0, mod->core_size); | 2790 | memset(ptr, 0, mod->core_size); |
2739 | mod->module_core = ptr; | 2791 | mod->module_core = ptr; |
2740 | 2792 | ||
2741 | ptr = module_alloc_update_bounds(mod->init_size); | 2793 | if (mod->init_size) { |
2742 | /* | 2794 | ptr = module_alloc_update_bounds(mod->init_size); |
2743 | * The pointer to this block is stored in the module structure | 2795 | /* |
2744 | * which is inside the block. This block doesn't need to be | 2796 | * The pointer to this block is stored in the module structure |
2745 | * scanned as it contains data and code that will be freed | 2797 | * which is inside the block. This block doesn't need to be |
2746 | * after the module is initialized. | 2798 | * scanned as it contains data and code that will be freed |
2747 | */ | 2799 | * after the module is initialized. |
2748 | kmemleak_ignore(ptr); | 2800 | */ |
2749 | if (!ptr && mod->init_size) { | 2801 | kmemleak_ignore(ptr); |
2750 | module_free(mod, mod->module_core); | 2802 | if (!ptr) { |
2751 | return -ENOMEM; | 2803 | module_free(mod, mod->module_core); |
2752 | } | 2804 | return -ENOMEM; |
2753 | memset(ptr, 0, mod->init_size); | 2805 | } |
2754 | mod->module_init = ptr; | 2806 | memset(ptr, 0, mod->init_size); |
2807 | mod->module_init = ptr; | ||
2808 | } else | ||
2809 | mod->module_init = NULL; | ||
2755 | 2810 | ||
2756 | /* Transfer each section which specifies SHF_ALLOC */ | 2811 | /* Transfer each section which specifies SHF_ALLOC */ |
2757 | pr_debug("final section addresses:\n"); | 2812 | pr_debug("final section addresses:\n"); |
@@ -2844,18 +2899,18 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr, | |||
2844 | return 0; | 2899 | return 0; |
2845 | } | 2900 | } |
2846 | 2901 | ||
2847 | static struct module *layout_and_allocate(struct load_info *info) | 2902 | static struct module *layout_and_allocate(struct load_info *info, int flags) |
2848 | { | 2903 | { |
2849 | /* Module within temporary copy. */ | 2904 | /* Module within temporary copy. */ |
2850 | struct module *mod; | 2905 | struct module *mod; |
2851 | Elf_Shdr *pcpusec; | 2906 | Elf_Shdr *pcpusec; |
2852 | int err; | 2907 | int err; |
2853 | 2908 | ||
2854 | mod = setup_load_info(info); | 2909 | mod = setup_load_info(info, flags); |
2855 | if (IS_ERR(mod)) | 2910 | if (IS_ERR(mod)) |
2856 | return mod; | 2911 | return mod; |
2857 | 2912 | ||
2858 | err = check_modinfo(mod, info); | 2913 | err = check_modinfo(mod, info, flags); |
2859 | if (err) | 2914 | if (err) |
2860 | return ERR_PTR(err); | 2915 | return ERR_PTR(err); |
2861 | 2916 | ||
@@ -2942,33 +2997,124 @@ static bool finished_loading(const char *name) | |||
2942 | return ret; | 2997 | return ret; |
2943 | } | 2998 | } |
2944 | 2999 | ||
3000 | /* Call module constructors. */ | ||
3001 | static void do_mod_ctors(struct module *mod) | ||
3002 | { | ||
3003 | #ifdef CONFIG_CONSTRUCTORS | ||
3004 | unsigned long i; | ||
3005 | |||
3006 | for (i = 0; i < mod->num_ctors; i++) | ||
3007 | mod->ctors[i](); | ||
3008 | #endif | ||
3009 | } | ||
3010 | |||
3011 | /* This is where the real work happens */ | ||
3012 | static int do_init_module(struct module *mod) | ||
3013 | { | ||
3014 | int ret = 0; | ||
3015 | |||
3016 | blocking_notifier_call_chain(&module_notify_list, | ||
3017 | MODULE_STATE_COMING, mod); | ||
3018 | |||
3019 | /* Set RO and NX regions for core */ | ||
3020 | set_section_ro_nx(mod->module_core, | ||
3021 | mod->core_text_size, | ||
3022 | mod->core_ro_size, | ||
3023 | mod->core_size); | ||
3024 | |||
3025 | /* Set RO and NX regions for init */ | ||
3026 | set_section_ro_nx(mod->module_init, | ||
3027 | mod->init_text_size, | ||
3028 | mod->init_ro_size, | ||
3029 | mod->init_size); | ||
3030 | |||
3031 | do_mod_ctors(mod); | ||
3032 | /* Start the module */ | ||
3033 | if (mod->init != NULL) | ||
3034 | ret = do_one_initcall(mod->init); | ||
3035 | if (ret < 0) { | ||
3036 | /* Init routine failed: abort. Try to protect us from | ||
3037 | buggy refcounters. */ | ||
3038 | mod->state = MODULE_STATE_GOING; | ||
3039 | synchronize_sched(); | ||
3040 | module_put(mod); | ||
3041 | blocking_notifier_call_chain(&module_notify_list, | ||
3042 | MODULE_STATE_GOING, mod); | ||
3043 | free_module(mod); | ||
3044 | wake_up_all(&module_wq); | ||
3045 | return ret; | ||
3046 | } | ||
3047 | if (ret > 0) { | ||
3048 | printk(KERN_WARNING | ||
3049 | "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" | ||
3050 | "%s: loading module anyway...\n", | ||
3051 | __func__, mod->name, ret, | ||
3052 | __func__); | ||
3053 | dump_stack(); | ||
3054 | } | ||
3055 | |||
3056 | /* Now it's a first class citizen! */ | ||
3057 | mod->state = MODULE_STATE_LIVE; | ||
3058 | blocking_notifier_call_chain(&module_notify_list, | ||
3059 | MODULE_STATE_LIVE, mod); | ||
3060 | |||
3061 | /* We need to finish all async code before the module init sequence is done */ | ||
3062 | async_synchronize_full(); | ||
3063 | |||
3064 | mutex_lock(&module_mutex); | ||
3065 | /* Drop initial reference. */ | ||
3066 | module_put(mod); | ||
3067 | trim_init_extable(mod); | ||
3068 | #ifdef CONFIG_KALLSYMS | ||
3069 | mod->num_symtab = mod->core_num_syms; | ||
3070 | mod->symtab = mod->core_symtab; | ||
3071 | mod->strtab = mod->core_strtab; | ||
3072 | #endif | ||
3073 | unset_module_init_ro_nx(mod); | ||
3074 | module_free(mod, mod->module_init); | ||
3075 | mod->module_init = NULL; | ||
3076 | mod->init_size = 0; | ||
3077 | mod->init_ro_size = 0; | ||
3078 | mod->init_text_size = 0; | ||
3079 | mutex_unlock(&module_mutex); | ||
3080 | wake_up_all(&module_wq); | ||
3081 | |||
3082 | return 0; | ||
3083 | } | ||
3084 | |||
3085 | static int may_init_module(void) | ||
3086 | { | ||
3087 | if (!capable(CAP_SYS_MODULE) || modules_disabled) | ||
3088 | return -EPERM; | ||
3089 | |||
3090 | return 0; | ||
3091 | } | ||
3092 | |||
2945 | /* Allocate and load the module: note that size of section 0 is always | 3093 | /* Allocate and load the module: note that size of section 0 is always |
2946 | zero, and we rely on this for optional sections. */ | 3094 | zero, and we rely on this for optional sections. */ |
2947 | static struct module *load_module(void __user *umod, | 3095 | static int load_module(struct load_info *info, const char __user *uargs, |
2948 | unsigned long len, | 3096 | int flags) |
2949 | const char __user *uargs) | ||
2950 | { | 3097 | { |
2951 | struct load_info info = { NULL, }; | ||
2952 | struct module *mod, *old; | 3098 | struct module *mod, *old; |
2953 | long err; | 3099 | long err; |
2954 | 3100 | ||
2955 | pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", | 3101 | err = module_sig_check(info); |
2956 | umod, len, uargs); | 3102 | if (err) |
3103 | goto free_copy; | ||
2957 | 3104 | ||
2958 | /* Copy in the blobs from userspace, check they are vaguely sane. */ | 3105 | err = elf_header_check(info); |
2959 | err = copy_and_check(&info, umod, len, uargs); | ||
2960 | if (err) | 3106 | if (err) |
2961 | return ERR_PTR(err); | 3107 | goto free_copy; |
2962 | 3108 | ||
2963 | /* Figure out module layout, and allocate all the memory. */ | 3109 | /* Figure out module layout, and allocate all the memory. */ |
2964 | mod = layout_and_allocate(&info); | 3110 | mod = layout_and_allocate(info, flags); |
2965 | if (IS_ERR(mod)) { | 3111 | if (IS_ERR(mod)) { |
2966 | err = PTR_ERR(mod); | 3112 | err = PTR_ERR(mod); |
2967 | goto free_copy; | 3113 | goto free_copy; |
2968 | } | 3114 | } |
2969 | 3115 | ||
2970 | #ifdef CONFIG_MODULE_SIG | 3116 | #ifdef CONFIG_MODULE_SIG |
2971 | mod->sig_ok = info.sig_ok; | 3117 | mod->sig_ok = info->sig_ok; |
2972 | if (!mod->sig_ok) | 3118 | if (!mod->sig_ok) |
2973 | add_taint_module(mod, TAINT_FORCED_MODULE); | 3119 | add_taint_module(mod, TAINT_FORCED_MODULE); |
2974 | #endif | 3120 | #endif |
@@ -2980,25 +3126,25 @@ static struct module *load_module(void __user *umod, | |||
2980 | 3126 | ||
2981 | /* Now we've got everything in the final locations, we can | 3127 | /* Now we've got everything in the final locations, we can |
2982 | * find optional sections. */ | 3128 | * find optional sections. */ |
2983 | find_module_sections(mod, &info); | 3129 | find_module_sections(mod, info); |
2984 | 3130 | ||
2985 | err = check_module_license_and_versions(mod); | 3131 | err = check_module_license_and_versions(mod); |
2986 | if (err) | 3132 | if (err) |
2987 | goto free_unload; | 3133 | goto free_unload; |
2988 | 3134 | ||
2989 | /* Set up MODINFO_ATTR fields */ | 3135 | /* Set up MODINFO_ATTR fields */ |
2990 | setup_modinfo(mod, &info); | 3136 | setup_modinfo(mod, info); |
2991 | 3137 | ||
2992 | /* Fix up syms, so that st_value is a pointer to location. */ | 3138 | /* Fix up syms, so that st_value is a pointer to location. */ |
2993 | err = simplify_symbols(mod, &info); | 3139 | err = simplify_symbols(mod, info); |
2994 | if (err < 0) | 3140 | if (err < 0) |
2995 | goto free_modinfo; | 3141 | goto free_modinfo; |
2996 | 3142 | ||
2997 | err = apply_relocations(mod, &info); | 3143 | err = apply_relocations(mod, info); |
2998 | if (err < 0) | 3144 | if (err < 0) |
2999 | goto free_modinfo; | 3145 | goto free_modinfo; |
3000 | 3146 | ||
3001 | err = post_relocation(mod, &info); | 3147 | err = post_relocation(mod, info); |
3002 | if (err < 0) | 3148 | if (err < 0) |
3003 | goto free_modinfo; | 3149 | goto free_modinfo; |
3004 | 3150 | ||
@@ -3038,14 +3184,14 @@ again: | |||
3038 | } | 3184 | } |
3039 | 3185 | ||
3040 | /* This has to be done once we're sure module name is unique. */ | 3186 | /* This has to be done once we're sure module name is unique. */ |
3041 | dynamic_debug_setup(info.debug, info.num_debug); | 3187 | dynamic_debug_setup(info->debug, info->num_debug); |
3042 | 3188 | ||
3043 | /* Find duplicate symbols */ | 3189 | /* Find duplicate symbols */ |
3044 | err = verify_export_symbols(mod); | 3190 | err = verify_export_symbols(mod); |
3045 | if (err < 0) | 3191 | if (err < 0) |
3046 | goto ddebug; | 3192 | goto ddebug; |
3047 | 3193 | ||
3048 | module_bug_finalize(info.hdr, info.sechdrs, mod); | 3194 | module_bug_finalize(info->hdr, info->sechdrs, mod); |
3049 | list_add_rcu(&mod->list, &modules); | 3195 | list_add_rcu(&mod->list, &modules); |
3050 | mutex_unlock(&module_mutex); | 3196 | mutex_unlock(&module_mutex); |
3051 | 3197 | ||
@@ -3056,16 +3202,17 @@ again: | |||
3056 | goto unlink; | 3202 | goto unlink; |
3057 | 3203 | ||
3058 | /* Link in to syfs. */ | 3204 | /* Link in to syfs. */ |
3059 | err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp); | 3205 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); |
3060 | if (err < 0) | 3206 | if (err < 0) |
3061 | goto unlink; | 3207 | goto unlink; |
3062 | 3208 | ||
3063 | /* Get rid of temporary copy. */ | 3209 | /* Get rid of temporary copy. */ |
3064 | free_copy(&info); | 3210 | free_copy(info); |
3065 | 3211 | ||
3066 | /* Done! */ | 3212 | /* Done! */ |
3067 | trace_module_load(mod); | 3213 | trace_module_load(mod); |
3068 | return mod; | 3214 | |
3215 | return do_init_module(mod); | ||
3069 | 3216 | ||
3070 | unlink: | 3217 | unlink: |
3071 | mutex_lock(&module_mutex); | 3218 | mutex_lock(&module_mutex); |
@@ -3074,7 +3221,7 @@ again: | |||
3074 | module_bug_cleanup(mod); | 3221 | module_bug_cleanup(mod); |
3075 | wake_up_all(&module_wq); | 3222 | wake_up_all(&module_wq); |
3076 | ddebug: | 3223 | ddebug: |
3077 | dynamic_debug_remove(info.debug); | 3224 | dynamic_debug_remove(info->debug); |
3078 | unlock: | 3225 | unlock: |
3079 | mutex_unlock(&module_mutex); | 3226 | mutex_unlock(&module_mutex); |
3080 | synchronize_sched(); | 3227 | synchronize_sched(); |
@@ -3086,106 +3233,52 @@ again: | |||
3086 | free_unload: | 3233 | free_unload: |
3087 | module_unload_free(mod); | 3234 | module_unload_free(mod); |
3088 | free_module: | 3235 | free_module: |
3089 | module_deallocate(mod, &info); | 3236 | module_deallocate(mod, info); |
3090 | free_copy: | 3237 | free_copy: |
3091 | free_copy(&info); | 3238 | free_copy(info); |
3092 | return ERR_PTR(err); | 3239 | return err; |
3093 | } | ||
3094 | |||
3095 | /* Call module constructors. */ | ||
3096 | static void do_mod_ctors(struct module *mod) | ||
3097 | { | ||
3098 | #ifdef CONFIG_CONSTRUCTORS | ||
3099 | unsigned long i; | ||
3100 | |||
3101 | for (i = 0; i < mod->num_ctors; i++) | ||
3102 | mod->ctors[i](); | ||
3103 | #endif | ||
3104 | } | 3240 | } |
3105 | 3241 | ||
3106 | /* This is where the real work happens */ | ||
3107 | SYSCALL_DEFINE3(init_module, void __user *, umod, | 3242 | SYSCALL_DEFINE3(init_module, void __user *, umod, |
3108 | unsigned long, len, const char __user *, uargs) | 3243 | unsigned long, len, const char __user *, uargs) |
3109 | { | 3244 | { |
3110 | struct module *mod; | 3245 | int err; |
3111 | int ret = 0; | 3246 | struct load_info info = { }; |
3112 | 3247 | ||
3113 | /* Must have permission */ | 3248 | err = may_init_module(); |
3114 | if (!capable(CAP_SYS_MODULE) || modules_disabled) | 3249 | if (err) |
3115 | return -EPERM; | 3250 | return err; |
3116 | 3251 | ||
3117 | /* Do all the hard work */ | 3252 | pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n", |
3118 | mod = load_module(umod, len, uargs); | 3253 | umod, len, uargs); |
3119 | if (IS_ERR(mod)) | ||
3120 | return PTR_ERR(mod); | ||
3121 | 3254 | ||
3122 | blocking_notifier_call_chain(&module_notify_list, | 3255 | err = copy_module_from_user(umod, len, &info); |
3123 | MODULE_STATE_COMING, mod); | 3256 | if (err) |
3257 | return err; | ||
3124 | 3258 | ||
3125 | /* Set RO and NX regions for core */ | 3259 | return load_module(&info, uargs, 0); |
3126 | set_section_ro_nx(mod->module_core, | 3260 | } |
3127 | mod->core_text_size, | ||
3128 | mod->core_ro_size, | ||
3129 | mod->core_size); | ||
3130 | 3261 | ||
3131 | /* Set RO and NX regions for init */ | 3262 | SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) |
3132 | set_section_ro_nx(mod->module_init, | 3263 | { |
3133 | mod->init_text_size, | 3264 | int err; |
3134 | mod->init_ro_size, | 3265 | struct load_info info = { }; |
3135 | mod->init_size); | ||
3136 | 3266 | ||
3137 | do_mod_ctors(mod); | 3267 | err = may_init_module(); |
3138 | /* Start the module */ | 3268 | if (err) |
3139 | if (mod->init != NULL) | 3269 | return err; |
3140 | ret = do_one_initcall(mod->init); | ||
3141 | if (ret < 0) { | ||
3142 | /* Init routine failed: abort. Try to protect us from | ||
3143 | buggy refcounters. */ | ||
3144 | mod->state = MODULE_STATE_GOING; | ||
3145 | synchronize_sched(); | ||
3146 | module_put(mod); | ||
3147 | blocking_notifier_call_chain(&module_notify_list, | ||
3148 | MODULE_STATE_GOING, mod); | ||
3149 | free_module(mod); | ||
3150 | wake_up_all(&module_wq); | ||
3151 | return ret; | ||
3152 | } | ||
3153 | if (ret > 0) { | ||
3154 | printk(KERN_WARNING | ||
3155 | "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" | ||
3156 | "%s: loading module anyway...\n", | ||
3157 | __func__, mod->name, ret, | ||
3158 | __func__); | ||
3159 | dump_stack(); | ||
3160 | } | ||
3161 | 3270 | ||
3162 | /* Now it's a first class citizen! */ | 3271 | pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags); |
3163 | mod->state = MODULE_STATE_LIVE; | ||
3164 | blocking_notifier_call_chain(&module_notify_list, | ||
3165 | MODULE_STATE_LIVE, mod); | ||
3166 | 3272 | ||
3167 | /* We need to finish all async code before the module init sequence is done */ | 3273 | if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS |
3168 | async_synchronize_full(); | 3274 | |MODULE_INIT_IGNORE_VERMAGIC)) |
3275 | return -EINVAL; | ||
3169 | 3276 | ||
3170 | mutex_lock(&module_mutex); | 3277 | err = copy_module_from_fd(fd, &info); |
3171 | /* Drop initial reference. */ | 3278 | if (err) |
3172 | module_put(mod); | 3279 | return err; |
3173 | trim_init_extable(mod); | ||
3174 | #ifdef CONFIG_KALLSYMS | ||
3175 | mod->num_symtab = mod->core_num_syms; | ||
3176 | mod->symtab = mod->core_symtab; | ||
3177 | mod->strtab = mod->core_strtab; | ||
3178 | #endif | ||
3179 | unset_module_init_ro_nx(mod); | ||
3180 | module_free(mod, mod->module_init); | ||
3181 | mod->module_init = NULL; | ||
3182 | mod->init_size = 0; | ||
3183 | mod->init_ro_size = 0; | ||
3184 | mod->init_text_size = 0; | ||
3185 | mutex_unlock(&module_mutex); | ||
3186 | wake_up_all(&module_wq); | ||
3187 | 3280 | ||
3188 | return 0; | 3281 | return load_module(&info, uargs, flags); |
3189 | } | 3282 | } |
3190 | 3283 | ||
3191 | static inline int within(unsigned long addr, void *start, unsigned long size) | 3284 | static inline int within(unsigned long addr, void *start, unsigned long size) |
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index d73840271dce..a278cad1d5d6 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
10 | #include <linux/kernel_stat.h> | 10 | #include <linux/kernel_stat.h> |
11 | #include <trace/events/timer.h> | 11 | #include <trace/events/timer.h> |
12 | #include <linux/random.h> | ||
12 | 13 | ||
13 | /* | 14 | /* |
14 | * Called after updating RLIMIT_CPU to run cpu timer and update | 15 | * Called after updating RLIMIT_CPU to run cpu timer and update |
@@ -470,6 +471,8 @@ static void cleanup_timers(struct list_head *head, | |||
470 | */ | 471 | */ |
471 | void posix_cpu_timers_exit(struct task_struct *tsk) | 472 | void posix_cpu_timers_exit(struct task_struct *tsk) |
472 | { | 473 | { |
474 | add_device_randomness((const void*) &tsk->se.sum_exec_runtime, | ||
475 | sizeof(unsigned long long)); | ||
473 | cleanup_timers(tsk->cpu_timers, | 476 | cleanup_timers(tsk->cpu_timers, |
474 | tsk->utime, tsk->stime, tsk->se.sum_exec_runtime); | 477 | tsk->utime, tsk->stime, tsk->se.sum_exec_runtime); |
475 | 478 | ||
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index dbff751e4086..395084d4ce16 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
@@ -25,6 +25,7 @@ cond_syscall(sys_swapoff); | |||
25 | cond_syscall(sys_kexec_load); | 25 | cond_syscall(sys_kexec_load); |
26 | cond_syscall(compat_sys_kexec_load); | 26 | cond_syscall(compat_sys_kexec_load); |
27 | cond_syscall(sys_init_module); | 27 | cond_syscall(sys_init_module); |
28 | cond_syscall(sys_finit_module); | ||
28 | cond_syscall(sys_delete_module); | 29 | cond_syscall(sys_delete_module); |
29 | cond_syscall(sys_socketpair); | 30 | cond_syscall(sys_socketpair); |
30 | cond_syscall(sys_bind); | 31 | cond_syscall(sys_bind); |
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 997c6a16ec22..75a2ab3d0b02 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c | |||
@@ -344,6 +344,10 @@ static void watchdog_enable(unsigned int cpu) | |||
344 | { | 344 | { |
345 | struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); | 345 | struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); |
346 | 346 | ||
347 | /* kick off the timer for the hardlockup detector */ | ||
348 | hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
349 | hrtimer->function = watchdog_timer_fn; | ||
350 | |||
347 | if (!watchdog_enabled) { | 351 | if (!watchdog_enabled) { |
348 | kthread_park(current); | 352 | kthread_park(current); |
349 | return; | 353 | return; |
@@ -352,10 +356,6 @@ static void watchdog_enable(unsigned int cpu) | |||
352 | /* Enable the perf event */ | 356 | /* Enable the perf event */ |
353 | watchdog_nmi_enable(cpu); | 357 | watchdog_nmi_enable(cpu); |
354 | 358 | ||
355 | /* kick off the timer for the hardlockup detector */ | ||
356 | hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
357 | hrtimer->function = watchdog_timer_fn; | ||
358 | |||
359 | /* done here because hrtimer_start can only pin to smp_processor_id() */ | 359 | /* done here because hrtimer_start can only pin to smp_processor_id() */ |
360 | hrtimer_start(hrtimer, ns_to_ktime(sample_period), | 360 | hrtimer_start(hrtimer, ns_to_ktime(sample_period), |
361 | HRTIMER_MODE_REL_PINNED); | 361 | HRTIMER_MODE_REL_PINNED); |
@@ -369,9 +369,6 @@ static void watchdog_disable(unsigned int cpu) | |||
369 | { | 369 | { |
370 | struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); | 370 | struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); |
371 | 371 | ||
372 | if (!watchdog_enabled) | ||
373 | return; | ||
374 | |||
375 | watchdog_set_prio(SCHED_NORMAL, 0); | 372 | watchdog_set_prio(SCHED_NORMAL, 0); |
376 | hrtimer_cancel(hrtimer); | 373 | hrtimer_cancel(hrtimer); |
377 | /* disable the perf event */ | 374 | /* disable the perf event */ |
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 5293d2433029..11b9b01fda6b 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c | |||
@@ -81,7 +81,7 @@ next_tag: | |||
81 | goto next_tag; | 81 | goto next_tag; |
82 | } | 82 | } |
83 | 83 | ||
84 | if (unlikely((tag & 0x1f) == 0x1f)) { | 84 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) { |
85 | do { | 85 | do { |
86 | if (unlikely(datalen - dp < 2)) | 86 | if (unlikely(datalen - dp < 2)) |
87 | goto data_overrun_error; | 87 | goto data_overrun_error; |
@@ -96,7 +96,7 @@ next_tag: | |||
96 | goto next_tag; | 96 | goto next_tag; |
97 | } | 97 | } |
98 | 98 | ||
99 | if (unlikely(len == 0x80)) { | 99 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { |
100 | /* Indefinite length */ | 100 | /* Indefinite length */ |
101 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) | 101 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) |
102 | goto indefinite_len_primitive; | 102 | goto indefinite_len_primitive; |
@@ -222,7 +222,7 @@ next_op: | |||
222 | if (unlikely(dp >= datalen - 1)) | 222 | if (unlikely(dp >= datalen - 1)) |
223 | goto data_overrun_error; | 223 | goto data_overrun_error; |
224 | tag = data[dp++]; | 224 | tag = data[dp++]; |
225 | if (unlikely((tag & 0x1f) == 0x1f)) | 225 | if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) |
226 | goto long_tag_not_supported; | 226 | goto long_tag_not_supported; |
227 | 227 | ||
228 | if (op & ASN1_OP_MATCH__ANY) { | 228 | if (op & ASN1_OP_MATCH__ANY) { |
@@ -254,7 +254,7 @@ next_op: | |||
254 | 254 | ||
255 | len = data[dp++]; | 255 | len = data[dp++]; |
256 | if (len > 0x7f) { | 256 | if (len > 0x7f) { |
257 | if (unlikely(len == 0x80)) { | 257 | if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { |
258 | /* Indefinite length */ | 258 | /* Indefinite length */ |
259 | if (unlikely(!(tag & ASN1_CONS_BIT))) | 259 | if (unlikely(!(tag & ASN1_CONS_BIT))) |
260 | goto indefinite_len_primitive; | 260 | goto indefinite_len_primitive; |
diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign new file mode 100644 index 000000000000..abfda626dbad --- /dev/null +++ b/scripts/Makefile.modsign | |||
@@ -0,0 +1,32 @@ | |||
1 | # ========================================================================== | ||
2 | # Signing modules | ||
3 | # ========================================================================== | ||
4 | |||
5 | PHONY := __modsign | ||
6 | __modsign: | ||
7 | |||
8 | include scripts/Kbuild.include | ||
9 | |||
10 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) | ||
11 | modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) | ||
12 | |||
13 | PHONY += $(modules) | ||
14 | __modsign: $(modules) | ||
15 | @: | ||
16 | |||
17 | quiet_cmd_sign_ko = SIGN [M] $(2)/$(notdir $@) | ||
18 | cmd_sign_ko = $(mod_sign_cmd) $(2)/$(notdir $@) | ||
19 | |||
20 | # Modules built outside the kernel source tree go into extra by default | ||
21 | INSTALL_MOD_DIR ?= extra | ||
22 | ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) | ||
23 | |||
24 | modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) | ||
25 | |||
26 | $(modules): | ||
27 | $(call cmd,sign_ko,$(MODLIB)/$(modinst_dir)) | ||
28 | |||
29 | # Declare the contents of the .PHONY variable as phony. We keep that | ||
30 | # information in a variable se we can use it in if_changed and friends. | ||
31 | |||
32 | .PHONY: $(PHONY) | ||
diff --git a/security/capability.c b/security/capability.c index b14a30c234b8..0fe5a026aef8 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -395,6 +395,11 @@ static int cap_kernel_module_request(char *kmod_name) | |||
395 | return 0; | 395 | return 0; |
396 | } | 396 | } |
397 | 397 | ||
398 | static int cap_kernel_module_from_file(struct file *file) | ||
399 | { | ||
400 | return 0; | ||
401 | } | ||
402 | |||
398 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) | 403 | static int cap_task_setpgid(struct task_struct *p, pid_t pgid) |
399 | { | 404 | { |
400 | return 0; | 405 | return 0; |
@@ -967,6 +972,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
967 | set_to_cap_if_null(ops, kernel_act_as); | 972 | set_to_cap_if_null(ops, kernel_act_as); |
968 | set_to_cap_if_null(ops, kernel_create_files_as); | 973 | set_to_cap_if_null(ops, kernel_create_files_as); |
969 | set_to_cap_if_null(ops, kernel_module_request); | 974 | set_to_cap_if_null(ops, kernel_module_request); |
975 | set_to_cap_if_null(ops, kernel_module_from_file); | ||
970 | set_to_cap_if_null(ops, task_fix_setuid); | 976 | set_to_cap_if_null(ops, task_fix_setuid); |
971 | set_to_cap_if_null(ops, task_setpgid); | 977 | set_to_cap_if_null(ops, task_setpgid); |
972 | set_to_cap_if_null(ops, task_getpgid); | 978 | set_to_cap_if_null(ops, task_getpgid); |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6ee8826662cc..3b2adb794f15 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -127,7 +127,7 @@ struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | |||
127 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | 127 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); |
128 | 128 | ||
129 | /* IMA policy related functions */ | 129 | /* IMA policy related functions */ |
130 | enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, POST_SETATTR }; | 130 | enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK, MODULE_CHECK, POST_SETATTR }; |
131 | 131 | ||
132 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | 132 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, |
133 | int flags); | 133 | int flags); |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index b356884fb3ef..0cea3db21657 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -100,12 +100,12 @@ err_out: | |||
100 | * ima_get_action - appraise & measure decision based on policy. | 100 | * ima_get_action - appraise & measure decision based on policy. |
101 | * @inode: pointer to inode to measure | 101 | * @inode: pointer to inode to measure |
102 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) | 102 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) |
103 | * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) | 103 | * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP, MODULE_CHECK) |
104 | * | 104 | * |
105 | * The policy is defined in terms of keypairs: | 105 | * The policy is defined in terms of keypairs: |
106 | * subj=, obj=, type=, func=, mask=, fsmagic= | 106 | * subj=, obj=, type=, func=, mask=, fsmagic= |
107 | * subj,obj, and type: are LSM specific. | 107 | * subj,obj, and type: are LSM specific. |
108 | * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP | 108 | * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP | MODULE_CHECK |
109 | * mask: contains the permission mask | 109 | * mask: contains the permission mask |
110 | * fsmagic: hex value | 110 | * fsmagic: hex value |
111 | * | 111 | * |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 73c9a268253e..45de18e9a6f2 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -280,6 +280,27 @@ int ima_file_check(struct file *file, int mask) | |||
280 | } | 280 | } |
281 | EXPORT_SYMBOL_GPL(ima_file_check); | 281 | EXPORT_SYMBOL_GPL(ima_file_check); |
282 | 282 | ||
283 | /** | ||
284 | * ima_module_check - based on policy, collect/store/appraise measurement. | ||
285 | * @file: pointer to the file to be measured/appraised | ||
286 | * | ||
287 | * Measure/appraise kernel modules based on policy. | ||
288 | * | ||
289 | * Always return 0 and audit dentry_open failures. | ||
290 | * Return code is based upon measurement appraisal. | ||
291 | */ | ||
292 | int ima_module_check(struct file *file) | ||
293 | { | ||
294 | int rc; | ||
295 | |||
296 | if (!file) | ||
297 | rc = INTEGRITY_UNKNOWN; | ||
298 | else | ||
299 | rc = process_measurement(file, file->f_dentry->d_name.name, | ||
300 | MAY_EXEC, MODULE_CHECK); | ||
301 | return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; | ||
302 | } | ||
303 | |||
283 | static int __init init_ima(void) | 304 | static int __init init_ima(void) |
284 | { | 305 | { |
285 | int error; | 306 | int error; |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index c7dacd2eab7a..af7d182d5a46 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
@@ -80,6 +80,7 @@ static struct ima_rule_entry default_rules[] = { | |||
80 | .flags = IMA_FUNC | IMA_MASK}, | 80 | .flags = IMA_FUNC | IMA_MASK}, |
81 | {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID, | 81 | {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID, |
82 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | 82 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, |
83 | {.action = MEASURE,.func = MODULE_CHECK, .flags = IMA_FUNC}, | ||
83 | }; | 84 | }; |
84 | 85 | ||
85 | static struct ima_rule_entry default_appraise_rules[] = { | 86 | static struct ima_rule_entry default_appraise_rules[] = { |
@@ -401,6 +402,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
401 | /* PATH_CHECK is for backwards compat */ | 402 | /* PATH_CHECK is for backwards compat */ |
402 | else if (strcmp(args[0].from, "PATH_CHECK") == 0) | 403 | else if (strcmp(args[0].from, "PATH_CHECK") == 0) |
403 | entry->func = FILE_CHECK; | 404 | entry->func = FILE_CHECK; |
405 | else if (strcmp(args[0].from, "MODULE_CHECK") == 0) | ||
406 | entry->func = MODULE_CHECK; | ||
404 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) | 407 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) |
405 | entry->func = FILE_MMAP; | 408 | entry->func = FILE_MMAP; |
406 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) | 409 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) |
diff --git a/security/security.c b/security/security.c index 8dcd4ae10a5f..daa97f4ac9d1 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -820,6 +820,16 @@ int security_kernel_module_request(char *kmod_name) | |||
820 | return security_ops->kernel_module_request(kmod_name); | 820 | return security_ops->kernel_module_request(kmod_name); |
821 | } | 821 | } |
822 | 822 | ||
823 | int security_kernel_module_from_file(struct file *file) | ||
824 | { | ||
825 | int ret; | ||
826 | |||
827 | ret = security_ops->kernel_module_from_file(file); | ||
828 | if (ret) | ||
829 | return ret; | ||
830 | return ima_module_check(file); | ||
831 | } | ||
832 | |||
823 | int security_task_fix_setuid(struct cred *new, const struct cred *old, | 833 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
824 | int flags) | 834 | int flags) |
825 | { | 835 | { |