diff --git a/[refs] b/[refs] index f5e2e84ea43f..3c712039f698 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 829f51dbd825256197fb2a89705d42ad83f958ef +refs/heads/master: 0fd7bee1e9b68fd271ad87c3e705facd1ca38055 diff --git a/trunk/Documentation/ABI/testing/sysfs-class-mtd b/trunk/Documentation/ABI/testing/sysfs-class-mtd index db1ad7e34fc3..4d55a1888981 100644 --- a/trunk/Documentation/ABI/testing/sysfs-class-mtd +++ b/trunk/Documentation/ABI/testing/sysfs-class-mtd @@ -123,54 +123,3 @@ Description: half page, or a quarter page). In the case of ECC NOR, it is the ECC block size. - -What: /sys/class/mtd/mtdX/ecc_strength -Date: April 2012 -KernelVersion: 3.4 -Contact: linux-mtd@lists.infradead.org -Description: - Maximum number of bit errors that the device is capable of - correcting within each region covering an ecc step. This will - always be a non-negative integer. Note that some devices will - have multiple ecc steps within each writesize region. - - In the case of devices lacking any ECC capability, it is 0. - -What: /sys/class/mtd/mtdX/bitflip_threshold -Date: April 2012 -KernelVersion: 3.4 -Contact: linux-mtd@lists.infradead.org -Description: - This allows the user to examine and adjust the criteria by which - mtd returns -EUCLEAN from mtd_read(). If the maximum number of - bit errors that were corrected on any single region comprising - an ecc step (as reported by the driver) equals or exceeds this - value, -EUCLEAN is returned. Otherwise, absent an error, 0 is - returned. Higher layers (e.g., UBI) use this return code as an - indication that an erase block may be degrading and should be - scrutinized as a candidate for being marked as bad. - - The initial value may be specified by the flash device driver. - If not, then the default value is ecc_strength. - - The introduction of this feature brings a subtle change to the - meaning of the -EUCLEAN return code. Previously, it was - interpreted to mean simply "one or more bit errors were - corrected". Its new interpretation can be phrased as "a - dangerously high number of bit errors were corrected on one or - more regions comprising an ecc step". The precise definition of - "dangerously high" can be adjusted by the user with - bitflip_threshold. Users are discouraged from doing this, - however, unless they know what they are doing and have intimate - knowledge of the properties of their device. Broadly speaking, - bitflip_threshold should be low enough to detect genuine erase - block degradation, but high enough to avoid the consequences of - a persistent return value of -EUCLEAN on devices where sticky - bitflips occur. Note that if bitflip_threshold exceeds - ecc_strength, -EUCLEAN is never returned by mtd_read(). - Conversely, if bitflip_threshold is zero, -EUCLEAN is always - returned, absent a hard error. - - This is generally applicable only to NAND flash devices with ECC - capability. It is ignored on devices lacking ECC capability; - i.e., devices for which ecc_strength is zero. diff --git a/trunk/Documentation/DocBook/mtdnand.tmpl b/trunk/Documentation/DocBook/mtdnand.tmpl index e0aedb7a7827..0c674be0d3c6 100644 --- a/trunk/Documentation/DocBook/mtdnand.tmpl +++ b/trunk/Documentation/DocBook/mtdnand.tmpl @@ -1119,6 +1119,8 @@ in this page These constants are defined in nand.h. They are ored together to describe the chip functionality. +/* Chip can not auto increment pages */ +#define NAND_NO_AUTOINCR 0x00000001 /* Buswitdh is 16 bit */ #define NAND_BUSWIDTH_16 0x00000002 /* Device supports partial programming without padding */ diff --git a/trunk/Documentation/arm/OMAP/DSS b/trunk/Documentation/arm/OMAP/DSS index a564ceea9e98..888ae7b83ae4 100644 --- a/trunk/Documentation/arm/OMAP/DSS +++ b/trunk/Documentation/arm/OMAP/DSS @@ -47,51 +47,6 @@ flexible way to enable non-common multi-display configuration. In addition to modelling the hardware overlays, omapdss supports virtual overlays and overlay managers. These can be used when updating a display with CPU or system DMA. -omapdss driver support for audio --------------------------------- -There exist several display technologies and standards that support audio as -well. Hence, it is relevant to update the DSS device driver to provide an audio -interface that may be used by an audio driver or any other driver interested in -the functionality. - -The audio_enable function is intended to prepare the relevant -IP for playback (e.g., enabling an audio FIFO, taking in/out of reset -some IP, enabling companion chips, etc). It is intended to be called before -audio_start. The audio_disable function performs the reverse operation and is -intended to be called after audio_stop. - -While a given DSS device driver may support audio, it is possible that for -certain configurations audio is not supported (e.g., an HDMI display using a -VESA video timing). The audio_supported function is intended to query whether -the current configuration of the display supports audio. - -The audio_config function is intended to configure all the relevant audio -parameters of the display. In order to make the function independent of any -specific DSS device driver, a struct omap_dss_audio is defined. Its purpose -is to contain all the required parameters for audio configuration. At the -moment, such structure contains pointers to IEC-60958 channel status word -and CEA-861 audio infoframe structures. This should be enough to support -HDMI and DisplayPort, as both are based on CEA-861 and IEC-60958. - -The audio_enable/disable, audio_config and audio_supported functions could be -implemented as functions that may sleep. Hence, they should not be called -while holding a spinlock or a readlock. - -The audio_start/audio_stop function is intended to effectively start/stop audio -playback after the configuration has taken place. These functions are designed -to be used in an atomic context. Hence, audio_start should return quickly and be -called only after all the needed resources for audio playback (audio FIFOs, -DMA channels, companion chips, etc) have been enabled to begin data transfers. -audio_stop is designed to only stop the audio transfers. The resources used -for playback are released using audio_disable. - -The enum omap_dss_audio_state may be used to help the implementations of -the interface to keep track of the audio state. The initial state is _DISABLED; -then, the state transitions to _CONFIGURED, and then, when it is ready to -play audio, to _ENABLED. The state _PLAYING is used when the audio is being -rendered. - - Panel and controller drivers ---------------------------- @@ -201,7 +156,6 @@ timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw) "pal" and "ntsc" panel_name tear_elim Tearing elimination 0=off, 1=on -output_type Output type (video encoder only): "composite" or "svideo" There are also some debugfs files at /omapdss/ which show information about clocks and registers. diff --git a/trunk/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/trunk/Documentation/devicetree/bindings/mtd/gpmi-nand.txt deleted file mode 100644 index 1a5bbd346d22..000000000000 --- a/trunk/Documentation/devicetree/bindings/mtd/gpmi-nand.txt +++ /dev/null @@ -1,33 +0,0 @@ -* Freescale General-Purpose Media Interface (GPMI) - -The GPMI nand controller provides an interface to control the -NAND flash chips. We support only one NAND chip now. - -Required properties: - - compatible : should be "fsl,-gpmi-nand" - - reg : should contain registers location and length for gpmi and bch. - - reg-names: Should contain the reg names "gpmi-nand" and "bch" - - interrupts : The first is the DMA interrupt number for GPMI. - The second is the BCH interrupt number. - - interrupt-names : The interrupt names "gpmi-dma", "bch"; - - fsl,gpmi-dma-channel : Should contain the dma channel it uses. - -The device tree may optionally contain sub-nodes describing partitions of the -address space. See partition.txt for more detail. - -Examples: - -gpmi-nand@8000c000 { - compatible = "fsl,imx28-gpmi-nand"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x8000c000 2000>, <0x8000a000 2000>; - reg-names = "gpmi-nand", "bch"; - interrupts = <88>, <41>; - interrupt-names = "gpmi-dma", "bch"; - fsl,gpmi-dma-channel = <4>; - - partition@0 { - ... - }; -}; diff --git a/trunk/Documentation/devicetree/bindings/mtd/mxc-nand.txt b/trunk/Documentation/devicetree/bindings/mtd/mxc-nand.txt deleted file mode 100644 index b5833d11c7be..000000000000 --- a/trunk/Documentation/devicetree/bindings/mtd/mxc-nand.txt +++ /dev/null @@ -1,19 +0,0 @@ -* Freescale's mxc_nand - -Required properties: -- compatible: "fsl,imxXX-nand" -- reg: address range of the nfc block -- interrupts: irq to be used -- nand-bus-width: see nand.txt -- nand-ecc-mode: see nand.txt -- nand-on-flash-bbt: see nand.txt - -Example: - - nand@d8000000 { - compatible = "fsl,imx27-nand"; - reg = <0xd8000000 0x1000>; - interrupts = <29>; - nand-bus-width = <8>; - nand-ecc-mode = "hw"; - }; diff --git a/trunk/Documentation/vm/slub.txt b/trunk/Documentation/vm/slub.txt index b0c6d1bbb434..6752870c4970 100644 --- a/trunk/Documentation/vm/slub.txt +++ b/trunk/Documentation/vm/slub.txt @@ -17,7 +17,7 @@ data and perform operation on the slabs. By default slabinfo only lists slabs that have data in them. See "slabinfo -h" for more options when running the command. slabinfo can be compiled with -gcc -o slabinfo tools/vm/slabinfo.c +gcc -o slabinfo tools/slub/slabinfo.c Some of the modes of operation of slabinfo require that slub debugging be enabled on the command line. F.e. no tracking information will be diff --git a/trunk/arch/arm/boot/dts/db8500.dtsi b/trunk/arch/arm/boot/dts/db8500.dtsi index 4ad5160018cb..881bc3987844 100644 --- a/trunk/arch/arm/boot/dts/db8500.dtsi +++ b/trunk/arch/arm/boot/dts/db8500.dtsi @@ -58,8 +58,6 @@ "st,nomadik-gpio"; reg = <0x8012e000 0x80>; interrupts = <0 119 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -71,8 +69,6 @@ "st,nomadik-gpio"; reg = <0x8012e080 0x80>; interrupts = <0 120 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -84,8 +80,6 @@ "st,nomadik-gpio"; reg = <0x8000e000 0x80>; interrupts = <0 121 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -97,8 +91,6 @@ "st,nomadik-gpio"; reg = <0x8000e080 0x80>; interrupts = <0 122 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -110,8 +102,6 @@ "st,nomadik-gpio"; reg = <0x8000e100 0x80>; interrupts = <0 123 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -123,8 +113,6 @@ "st,nomadik-gpio"; reg = <0x8000e180 0x80>; interrupts = <0 124 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -136,8 +124,6 @@ "st,nomadik-gpio"; reg = <0x8011e000 0x80>; interrupts = <0 125 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -149,8 +135,6 @@ "st,nomadik-gpio"; reg = <0x8011e080 0x80>; interrupts = <0 126 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -162,18 +146,12 @@ "st,nomadik-gpio"; reg = <0xa03fe000 0x80>; interrupts = <0 127 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; gpio-bank = <8>; }; - pinctrl { - compatible = "stericsson,nmk_pinctrl"; - }; - usb@a03e0000 { compatible = "stericsson,db8500-musb", "mentor,musb"; @@ -191,195 +169,20 @@ prcmu@80157000 { compatible = "stericsson,db8500-prcmu"; reg = <0x80157000 0x1000>; - interrupts = <0 47 0x4>; + interrupts = <46 47>; #address-cells = <1>; #size-cells = <1>; ranges; - prcmu-timer-4@80157450 { + prcmu-timer-4@80157450 { compatible = "stericsson,db8500-prcmu-timer-4"; reg = <0x80157450 0xC>; }; - db8500-prcmu-regulators { - compatible = "stericsson,db8500-prcmu-regulator"; - - // DB8500_REGULATOR_VAPE - db8500_vape_reg: db8500_vape { - regulator-name = "db8500-vape"; - regulator-always-on; - }; - - // DB8500_REGULATOR_VARM - db8500_varm_reg: db8500_varm { - regulator-name = "db8500-varm"; - }; - - // DB8500_REGULATOR_VMODEM - db8500_vmodem_reg: db8500_vmodem { - regulator-name = "db8500-vmodem"; - }; - - // DB8500_REGULATOR_VPLL - db8500_vpll_reg: db8500_vpll { - regulator-name = "db8500-vpll"; - }; - - // DB8500_REGULATOR_VSMPS1 - db8500_vsmps1_reg: db8500_vsmps1 { - regulator-name = "db8500-vsmps1"; - }; - - // DB8500_REGULATOR_VSMPS2 - db8500_vsmps2_reg: db8500_vsmps2 { - regulator-name = "db8500-vsmps2"; - }; - - // DB8500_REGULATOR_VSMPS3 - db8500_vsmps3_reg: db8500_vsmps3 { - regulator-name = "db8500-vsmps3"; - }; - - // DB8500_REGULATOR_VRF1 - db8500_vrf1_reg: db8500_vrf1 { - regulator-name = "db8500-vrf1"; - }; - - // DB8500_REGULATOR_SWITCH_SVAMMDSP - db8500_sva_mmdsp_reg: db8500_sva_mmdsp { - regulator-name = "db8500-sva-mmdsp"; - }; - - // DB8500_REGULATOR_SWITCH_SVAMMDSPRET - db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret { - regulator-name = "db8500-sva-mmdsp-ret"; - }; - - // DB8500_REGULATOR_SWITCH_SVAPIPE - db8500_sva_pipe_reg: db8500_sva_pipe { - regulator-name = "db8500_sva_pipe"; - }; - - // DB8500_REGULATOR_SWITCH_SIAMMDSP - db8500_sia_mmdsp_reg: db8500_sia_mmdsp { - regulator-name = "db8500_sia_mmdsp"; - }; - - // DB8500_REGULATOR_SWITCH_SIAMMDSPRET - db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret { - regulator-name = "db8500-sia-mmdsp-ret"; - }; - - // DB8500_REGULATOR_SWITCH_SIAPIPE - db8500_sia_pipe_reg: db8500_sia_pipe { - regulator-name = "db8500-sia-pipe"; - }; - - // DB8500_REGULATOR_SWITCH_SGA - db8500_sga_reg: db8500_sga { - regulator-name = "db8500-sga"; - vin-supply = <&db8500_vape_reg>; - }; - - // DB8500_REGULATOR_SWITCH_B2R2_MCDE - db8500_b2r2_mcde_reg: db8500_b2r2_mcde { - regulator-name = "db8500-b2r2-mcde"; - vin-supply = <&db8500_vape_reg>; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM12 - db8500_esram12_reg: db8500_esram12 { - regulator-name = "db8500-esram12"; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM12RET - db8500_esram12_ret_reg: db8500_esram12_ret { - regulator-name = "db8500-esram12-ret"; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM34 - db8500_esram34_reg: db8500_esram34 { - regulator-name = "db8500-esram34"; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM34RET - db8500_esram34_ret_reg: db8500_esram34_ret { - regulator-name = "db8500-esram34-ret"; - }; - }; - ab8500@5 { compatible = "stericsson,ab8500"; reg = <5>; /* mailbox 5 is i2c */ interrupts = <0 40 0x4>; - - ab8500-regulators { - compatible = "stericsson,ab8500-regulator"; - - // supplies to the display/camera - ab8500_ldo_aux1_reg: ab8500_ldo_aux1 { - regulator-name = "V-DISPLAY"; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2900000>; - regulator-boot-on; - /* BUG: If turned off MMC will be affected. */ - regulator-always-on; - }; - - // supplies to the on-board eMMC - ab8500_ldo_aux2_reg: ab8500_ldo_aux2 { - regulator-name = "V-eMMC1"; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <3300000>; - }; - - // supply for VAUX3; SDcard slots - ab8500_ldo_aux3_reg: ab8500_ldo_aux3 { - regulator-name = "V-MMC-SD"; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <3300000>; - }; - - // supply for v-intcore12; VINTCORE12 LDO - ab8500_ldo_initcore_reg: ab8500_ldo_initcore { - regulator-name = "V-INTCORE"; - }; - - // supply for tvout; gpadc; TVOUT LDO - ab8500_ldo_tvout_reg: ab8500_ldo_tvout { - regulator-name = "V-TVOUT"; - }; - - // supply for ab8500-usb; USB LDO - ab8500_ldo_usb_reg: ab8500_ldo_usb { - regulator-name = "dummy"; - }; - - // supply for ab8500-vaudio; VAUDIO LDO - ab8500_ldo_audio_reg: ab8500_ldo_audio { - regulator-name = "V-AUD"; - }; - - // supply for v-anamic1 VAMic1-LDO - ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 { - regulator-name = "V-AMIC1"; - }; - - // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1 - ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 { - regulator-name = "V-AMIC2"; - }; - - // supply for v-dmic; VDMIC LDO - ab8500_ldo_dmic_reg: ab8500_ldo_dmic { - regulator-name = "V-DMIC"; - }; - - // supply for U8500 CSI/DSI; VANA LDO - ab8500_ldo_ana_reg: ab8500_ldo_ana { - regulator-name = "V-CSI/DSI"; - }; - }; }; }; @@ -432,8 +235,7 @@ status = "disabled"; // Add one of these for each child device - cs-gpios = <&gpio0 31 0x4 &gpio4 14 0x4 &gpio4 16 0x4 - &gpio6 22 0x4 &gpio7 0 0x4>; + cs-gpios = <&gpio0 31 &gpio4 14 &gpio4 16 &gpio6 22 &gpio7 0>; }; diff --git a/trunk/arch/arm/boot/dts/imx27.dtsi b/trunk/arch/arm/boot/dts/imx27.dtsi index 386c769c38d1..2b1a166d41f9 100644 --- a/trunk/arch/arm/boot/dts/imx27.dtsi +++ b/trunk/arch/arm/boot/dts/imx27.dtsi @@ -213,14 +213,5 @@ status = "disabled"; }; }; - nand@d8000000 { - #address-cells = <1>; - #size-cells = <1>; - - compatible = "fsl,imx27-nand"; - reg = <0xd8000000 0x1000>; - interrupts = <29>; - status = "disabled"; - }; }; }; diff --git a/trunk/arch/arm/boot/dts/snowball.dts b/trunk/arch/arm/boot/dts/snowball.dts index ec3c33975110..d99dc04f0d91 100644 --- a/trunk/arch/arm/boot/dts/snowball.dts +++ b/trunk/arch/arm/boot/dts/snowball.dts @@ -20,16 +20,6 @@ reg = <0x00000000 0x20000000>; }; - en_3v3_reg: en_3v3 { - compatible = "regulator-fixed"; - regulator-name = "en-3v3-fixed-supply"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpios = <&gpio0 26 0x4>; // 26 - startup-delay-us = <5000>; - enable-active-high; - }; - gpio_keys { compatible = "gpio-keys"; #address-cells = <1>; @@ -40,35 +30,35 @@ wakeup = <1>; linux,code = <2>; label = "userpb"; - gpios = <&gpio1 0 0x4>; + gpios = <&gpio1 0 0>; }; button@2 { debounce_interval = <50>; wakeup = <1>; linux,code = <3>; label = "extkb1"; - gpios = <&gpio4 23 0x4>; + gpios = <&gpio4 23 0>; }; button@3 { debounce_interval = <50>; wakeup = <1>; linux,code = <4>; label = "extkb2"; - gpios = <&gpio4 24 0x4>; + gpios = <&gpio4 24 0>; }; button@4 { debounce_interval = <50>; wakeup = <1>; linux,code = <5>; label = "extkb3"; - gpios = <&gpio5 1 0x4>; + gpios = <&gpio5 1 0>; }; button@5 { debounce_interval = <50>; wakeup = <1>; linux,code = <6>; label = "extkb4"; - gpios = <&gpio5 2 0x4>; + gpios = <&gpio5 2 0>; }; }; @@ -76,11 +66,12 @@ compatible = "gpio-leds"; used-led { label = "user_led"; - gpios = <&gpio4 14 0x4>; + gpios = <&gpio4 14>; }; }; soc-u9500 { + external-bus@50000000 { status = "okay"; @@ -89,9 +80,6 @@ reg = <0 0x10000>; interrupts = <12 0x1>; interrupt-parent = <&gpio4>; - vdd33a-supply = <&en_3v3_reg>; - vddvario-supply = <&db8500_vape_reg>; - reg-shift = <1>; reg-io-width = <2>; @@ -103,13 +91,11 @@ sdi@80126000 { status = "enabled"; - vmmc-supply = <&ab8500_ldo_aux3_reg>; - cd-gpios = <&gpio6 26 0x4>; // 218 + cd-gpios = <&gpio6 26>; }; sdi@80114000 { status = "enabled"; - vmmc-supply = <&ab8500_ldo_aux2_reg>; }; uart@80120000 { @@ -128,7 +114,7 @@ tc3589x@42 { //compatible = "tc3589x"; reg = <0x42>; - gpios = <&gpio6 25 0x4>; + interrupts = <25>; interrupt-parent = <&gpio6>; }; tps61052@33 { diff --git a/trunk/arch/arm/configs/u8500_defconfig b/trunk/arch/arm/configs/u8500_defconfig index 2d4f661d1cf6..7e84f453e8a6 100644 --- a/trunk/arch/arm/configs/u8500_defconfig +++ b/trunk/arch/arm/configs/u8500_defconfig @@ -75,7 +75,6 @@ CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y CONFIG_REGULATOR_AB8500=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_HID_SUPPORT is not set CONFIG_USB_GADGET=y CONFIG_AB8500_USB=y diff --git a/trunk/arch/arm/mach-ep93xx/snappercl15.c b/trunk/arch/arm/mach-ep93xx/snappercl15.c index 01abd3516a77..eb282378fa78 100644 --- a/trunk/arch/arm/mach-ep93xx/snappercl15.c +++ b/trunk/arch/arm/mach-ep93xx/snappercl15.c @@ -82,6 +82,8 @@ static int snappercl15_nand_dev_ready(struct mtd_info *mtd) return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY); } +static const char *snappercl15_nand_part_probes[] = {"cmdlinepart", NULL}; + static struct mtd_partition snappercl15_nand_parts[] = { { .name = "Kernel", @@ -98,8 +100,10 @@ static struct mtd_partition snappercl15_nand_parts[] = { static struct platform_nand_data snappercl15_nand_data = { .chip = { .nr_chips = 1, + .part_probe_types = snappercl15_nand_part_probes, .partitions = snappercl15_nand_parts, .nr_partitions = ARRAY_SIZE(snappercl15_nand_parts), + .options = NAND_NO_AUTOINCR, .chip_delay = 25, }, .ctrl = { diff --git a/trunk/arch/arm/mach-ep93xx/ts72xx.c b/trunk/arch/arm/mach-ep93xx/ts72xx.c index 75cab2d7ec73..d4ef339d961e 100644 --- a/trunk/arch/arm/mach-ep93xx/ts72xx.c +++ b/trunk/arch/arm/mach-ep93xx/ts72xx.c @@ -105,6 +105,8 @@ static int ts72xx_nand_device_ready(struct mtd_info *mtd) return !!(__raw_readb(addr) & 0x20); } +static const char *ts72xx_nand_part_probes[] = { "cmdlinepart", NULL }; + #define TS72XX_BOOTROM_PART_SIZE (SZ_16K) #define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) @@ -132,6 +134,7 @@ static struct platform_nand_data ts72xx_nand_data = { .nr_chips = 1, .chip_offset = 0, .chip_delay = 15, + .part_probe_types = ts72xx_nand_part_probes, .partitions = ts72xx_nand_parts, .nr_partitions = ARRAY_SIZE(ts72xx_nand_parts), }, diff --git a/trunk/arch/arm/mach-exynos/mach-nuri.c b/trunk/arch/arm/mach-exynos/mach-nuri.c index 656f8fc9addd..972983e392bc 100644 --- a/trunk/arch/arm/mach-exynos/mach-nuri.c +++ b/trunk/arch/arm/mach-exynos/mach-nuri.c @@ -237,29 +237,25 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { #else /* Frame Buffer */ static struct s3c_fb_pd_win nuri_fb_win0 = { + .win_mode = { + .left_margin = 64, + .right_margin = 16, + .upper_margin = 64, + .lower_margin = 1, + .hsync_len = 48, + .vsync_len = 3, + .xres = 1024, + .yres = 600, + .refresh = 60, + }, .max_bpp = 24, .default_bpp = 16, - .xres = 1024, - .yres = 600, .virtual_x = 1024, .virtual_y = 2 * 600, }; -static struct fb_videomode nuri_lcd_timing = { - .left_margin = 64, - .right_margin = 16, - .upper_margin = 64, - .lower_margin = 1, - .hsync_len = 48, - .vsync_len = 3, - .xres = 1024, - .yres = 600, - .refresh = 60, -}; - static struct s3c_fb_platdata nuri_fb_pdata __initdata = { .win[0] = &nuri_fb_win0, - .vtiming = &nuri_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-exynos/mach-origen.c b/trunk/arch/arm/mach-exynos/mach-origen.c index f5572be9d7bf..a7f7fd567dde 100644 --- a/trunk/arch/arm/mach-exynos/mach-origen.c +++ b/trunk/arch/arm/mach-exynos/mach-origen.c @@ -604,28 +604,24 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { }; #else static struct s3c_fb_pd_win origen_fb_win0 = { - .xres = 1024, - .yres = 600, + .win_mode = { + .left_margin = 64, + .right_margin = 16, + .upper_margin = 64, + .lower_margin = 16, + .hsync_len = 48, + .vsync_len = 3, + .xres = 1024, + .yres = 600, + }, .max_bpp = 32, .default_bpp = 24, .virtual_x = 1024, .virtual_y = 2 * 600, }; -static struct fb_videomode origen_lcd_timing = { - .left_margin = 64, - .right_margin = 16, - .upper_margin = 64, - .lower_margin = 16, - .hsync_len = 48, - .vsync_len = 3, - .xres = 1024, - .yres = 600, -}; - static struct s3c_fb_platdata origen_lcd_pdata __initdata = { .win[0] = &origen_fb_win0, - .vtiming = &origen_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | VIDCON1_INV_VCLK, diff --git a/trunk/arch/arm/mach-exynos/mach-smdkv310.c b/trunk/arch/arm/mach-exynos/mach-smdkv310.c index 262e9e446a96..70df1a0c2118 100644 --- a/trunk/arch/arm/mach-exynos/mach-smdkv310.c +++ b/trunk/arch/arm/mach-exynos/mach-smdkv310.c @@ -178,26 +178,22 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { }; #else static struct s3c_fb_pd_win smdkv310_fb_win0 = { - .max_bpp = 32, - .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdkv310_lcd_timing = { - .left_margin = 13, - .right_margin = 8, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, + .win_mode = { + .left_margin = 13, + .right_margin = 8, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 24, }; static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = { .win[0] = &smdkv310_fb_win0, - .vtiming = &smdkv310_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = exynos4_fimd0_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-exynos/mach-universal_c210.c b/trunk/arch/arm/mach-exynos/mach-universal_c210.c index cd92fa86ba41..083b44de9c10 100644 --- a/trunk/arch/arm/mach-exynos/mach-universal_c210.c +++ b/trunk/arch/arm/mach-exynos/mach-universal_c210.c @@ -843,29 +843,25 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { #else /* Frame Buffer */ static struct s3c_fb_pd_win universal_fb_win0 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 2, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 1, + .xres = 480, + .yres = 800, + .refresh = 55, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, .virtual_x = 480, .virtual_y = 2 * 800, }; -static struct fb_videomode universal_lcd_timing = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 1, - .xres = 480, - .yres = 800, - .refresh = 55, -}; - static struct s3c_fb_platdata universal_lcd_pdata __initdata = { .win[0] = &universal_fb_win0, - .vtiming = &universal_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN diff --git a/trunk/arch/arm/mach-imx/imx27-dt.c b/trunk/arch/arm/mach-imx/imx27-dt.c index eee0cc8d92a4..ed38d03c61f2 100644 --- a/trunk/arch/arm/mach-imx/imx27-dt.c +++ b/trunk/arch/arm/mach-imx/imx27-dt.c @@ -29,7 +29,6 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI2_BASE_ADDR, "imx27-cspi.1", NULL), OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI3_BASE_ADDR, "imx27-cspi.2", NULL), OF_DEV_AUXDATA("fsl,imx27-wdt", MX27_WDOG_BASE_ADDR, "imx2-wdt.0", NULL), - OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "mxc_nand.0", NULL), { /* sentinel */ } }; diff --git a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c index 108a9d3f382d..3d742aee1773 100644 --- a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -60,6 +60,8 @@ static struct platform_device ixdp425_flash = { #if defined(CONFIG_MTD_NAND_PLATFORM) || \ defined(CONFIG_MTD_NAND_PLATFORM_MODULE) +const char *part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition ixdp425_partitions[] = { { .name = "ixp400 NAND FS 0", @@ -98,6 +100,8 @@ static struct platform_nand_data ixdp425_flash_nand_data = { .chip = { .nr_chips = 1, .chip_delay = 30, + .options = NAND_NO_AUTOINCR, + .part_probe_types = part_probes, .partitions = ixdp425_partitions, .nr_partitions = ARRAY_SIZE(ixdp425_partitions), }, diff --git a/trunk/arch/arm/mach-nomadik/board-nhk8815.c b/trunk/arch/arm/mach-nomadik/board-nhk8815.c index 2e8d3e176bc7..58cacafcf662 100644 --- a/trunk/arch/arm/mach-nomadik/board-nhk8815.c +++ b/trunk/arch/arm/mach-nomadik/board-nhk8815.c @@ -111,7 +111,7 @@ static struct nomadik_nand_platform_data nhk8815_nand_data = { .parts = nhk8815_partitions, .nparts = ARRAY_SIZE(nhk8815_partitions), .options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING \ - | NAND_NO_READRDY, + | NAND_NO_READRDY | NAND_NO_AUTOINCR, .init = nhk8815_nand_init, }; diff --git a/trunk/arch/arm/mach-omap1/board-fsample.c b/trunk/arch/arm/mach-omap1/board-fsample.c index 6872f3fd400f..c7364fdbda05 100644 --- a/trunk/arch/arm/mach-omap1/board-fsample.c +++ b/trunk/arch/arm/mach-omap1/board-fsample.c @@ -192,11 +192,14 @@ static int nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN); } +static const char *part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data nand_data = { .chip = { .nr_chips = 1, .chip_offset = 0, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap1/board-h2.c b/trunk/arch/arm/mach-omap1/board-h2.c index a28e989a63f4..7e503686f7af 100644 --- a/trunk/arch/arm/mach-omap1/board-h2.c +++ b/trunk/arch/arm/mach-omap1/board-h2.c @@ -186,6 +186,8 @@ static int h2_nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(H2_NAND_RB_GPIO_PIN); } +static const char *h2_part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data h2_nand_platdata = { .chip = { .nr_chips = 1, @@ -193,6 +195,7 @@ static struct platform_nand_data h2_nand_platdata = { .nr_partitions = ARRAY_SIZE(h2_nand_partitions), .partitions = h2_nand_partitions, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = h2_part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap1/board-h3.c b/trunk/arch/arm/mach-omap1/board-h3.c index 108a8640fc6f..9fb03f189d93 100644 --- a/trunk/arch/arm/mach-omap1/board-h3.c +++ b/trunk/arch/arm/mach-omap1/board-h3.c @@ -188,6 +188,8 @@ static int nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(H3_NAND_RB_GPIO_PIN); } +static const char *part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data nand_platdata = { .chip = { .nr_chips = 1, @@ -195,6 +197,7 @@ static struct platform_nand_data nand_platdata = { .nr_partitions = ARRAY_SIZE(nand_partitions), .partitions = nand_partitions, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap1/board-perseus2.c b/trunk/arch/arm/mach-omap1/board-perseus2.c index 703d55ecffe2..f2cb24387c22 100644 --- a/trunk/arch/arm/mach-omap1/board-perseus2.c +++ b/trunk/arch/arm/mach-omap1/board-perseus2.c @@ -150,11 +150,14 @@ static int nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(P2_NAND_RB_GPIO_PIN); } +static const char *part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data nand_data = { .chip = { .nr_chips = 1, .chip_offset = 0, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap2/display.c b/trunk/arch/arm/mach-omap2/display.c index 54d49ddb9b81..db5a88a36c63 100644 --- a/trunk/arch/arm/mach-omap2/display.c +++ b/trunk/arch/arm/mach-omap2/display.c @@ -180,133 +180,16 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) omap4_dsi_mux_pads(dsi_id, 0); } -static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput) -{ - return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput); -} - -static struct platform_device *create_dss_pdev(const char *pdev_name, - int pdev_id, const char *oh_name, void *pdata, int pdata_len, - struct platform_device *parent) -{ - struct platform_device *pdev; - struct omap_device *od; - struct omap_hwmod *ohs[1]; - struct omap_hwmod *oh; - int r; - - oh = omap_hwmod_lookup(oh_name); - if (!oh) { - pr_err("Could not look up %s\n", oh_name); - r = -ENODEV; - goto err; - } - - pdev = platform_device_alloc(pdev_name, pdev_id); - if (!pdev) { - pr_err("Could not create pdev for %s\n", pdev_name); - r = -ENOMEM; - goto err; - } - - if (parent != NULL) - pdev->dev.parent = &parent->dev; - - if (pdev->id != -1) - dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - else - dev_set_name(&pdev->dev, "%s", pdev->name); - - ohs[0] = oh; - od = omap_device_alloc(pdev, ohs, 1, NULL, 0); - if (!od) { - pr_err("Could not alloc omap_device for %s\n", pdev_name); - r = -ENOMEM; - goto err; - } - - r = platform_device_add_data(pdev, pdata, pdata_len); - if (r) { - pr_err("Could not set pdata for %s\n", pdev_name); - goto err; - } - - r = omap_device_register(pdev); - if (r) { - pr_err("Could not register omap_device for %s\n", pdev_name); - goto err; - } - - return pdev; - -err: - return ERR_PTR(r); -} - -static struct platform_device *create_simple_dss_pdev(const char *pdev_name, - int pdev_id, void *pdata, int pdata_len, - struct platform_device *parent) -{ - struct platform_device *pdev; - int r; - - pdev = platform_device_alloc(pdev_name, pdev_id); - if (!pdev) { - pr_err("Could not create pdev for %s\n", pdev_name); - r = -ENOMEM; - goto err; - } - - if (parent != NULL) - pdev->dev.parent = &parent->dev; - - if (pdev->id != -1) - dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - else - dev_set_name(&pdev->dev, "%s", pdev->name); - - r = platform_device_add_data(pdev, pdata, pdata_len); - if (r) { - pr_err("Could not set pdata for %s\n", pdev_name); - goto err; - } - - r = omap_device_register(pdev); - if (r) { - pr_err("Could not register omap_device for %s\n", pdev_name); - goto err; - } - - return pdev; - -err: - return ERR_PTR(r); -} - int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; + struct omap_hwmod *oh; struct platform_device *pdev; int i, oh_count; + struct omap_display_platform_data pdata; const struct omap_dss_hwmod_data *curr_dss_hwmod; - struct platform_device *dss_pdev; - - /* create omapdss device */ - - board_data->dsi_enable_pads = omap_dsi_enable_pads; - board_data->dsi_disable_pads = omap_dsi_disable_pads; - board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; - board_data->set_min_bus_tput = omap_dss_set_min_bus_tput; - - omap_display_device.dev.platform_data = board_data; - - r = platform_device_register(&omap_display_device); - if (r < 0) { - pr_err("Unable to register omapdss device\n"); - return r; - } - /* create devices for dss hwmods */ + memset(&pdata, 0, sizeof(pdata)); if (cpu_is_omap24xx()) { curr_dss_hwmod = omap2_dss_hwmod_data; @@ -319,58 +202,39 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); } - /* - * First create the pdev for dss_core, which is used as a parent device - * by the other dss pdevs. Note: dss_core has to be the first item in - * the hwmod list. - */ - dss_pdev = create_dss_pdev(curr_dss_hwmod[0].dev_name, - curr_dss_hwmod[0].id, - curr_dss_hwmod[0].oh_name, - board_data, sizeof(*board_data), - NULL); - - if (IS_ERR(dss_pdev)) { - pr_err("Could not build omap_device for %s\n", - curr_dss_hwmod[0].oh_name); - - return PTR_ERR(dss_pdev); - } - - for (i = 1; i < oh_count; i++) { - pdev = create_dss_pdev(curr_dss_hwmod[i].dev_name, - curr_dss_hwmod[i].id, - curr_dss_hwmod[i].oh_name, - board_data, sizeof(*board_data), - dss_pdev); - - if (IS_ERR(pdev)) { - pr_err("Could not build omap_device for %s\n", - curr_dss_hwmod[i].oh_name); - - return PTR_ERR(pdev); + if (board_data->dsi_enable_pads == NULL) + board_data->dsi_enable_pads = omap_dsi_enable_pads; + if (board_data->dsi_disable_pads == NULL) + board_data->dsi_disable_pads = omap_dsi_disable_pads; + + pdata.board_data = board_data; + pdata.board_data->get_context_loss_count = + omap_pm_get_dev_context_loss_count; + + for (i = 0; i < oh_count; i++) { + oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); + if (!oh) { + pr_err("Could not look up %s\n", + curr_dss_hwmod[i].oh_name); + return -ENODEV; } - } - /* Create devices for DPI and SDI */ + pdev = omap_device_build(curr_dss_hwmod[i].dev_name, + curr_dss_hwmod[i].id, oh, &pdata, + sizeof(struct omap_display_platform_data), + NULL, 0, 0); - pdev = create_simple_dss_pdev("omapdss_dpi", -1, - board_data, sizeof(*board_data), dss_pdev); - if (IS_ERR(pdev)) { - pr_err("Could not build platform_device for omapdss_dpi\n"); - return PTR_ERR(pdev); + if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n", + curr_dss_hwmod[i].oh_name)) + return -ENODEV; } + omap_display_device.dev.platform_data = board_data; - if (cpu_is_omap34xx()) { - pdev = create_simple_dss_pdev("omapdss_sdi", -1, - board_data, sizeof(*board_data), dss_pdev); - if (IS_ERR(pdev)) { - pr_err("Could not build platform_device for omapdss_sdi\n"); - return PTR_ERR(pdev); - } - } + r = platform_device_register(&omap_display_device); + if (r < 0) + printk(KERN_ERR "Unable to register OMAP-Display device\n"); - return 0; + return r; } static void dispc_disable_outputs(void) diff --git a/trunk/arch/arm/mach-omap2/gpmc.c b/trunk/arch/arm/mach-omap2/gpmc.c index 2286410671e7..46b09dae770e 100644 --- a/trunk/arch/arm/mach-omap2/gpmc.c +++ b/trunk/arch/arm/mach-omap2/gpmc.c @@ -49,7 +49,6 @@ #define GPMC_ECC_CONTROL 0x1f8 #define GPMC_ECC_SIZE_CONFIG 0x1fc #define GPMC_ECC1_RESULT 0x200 -#define GPMC_ECC_BCH_RESULT_0 0x240 /* not available on OMAP2 */ /* GPMC ECC control settings */ #define GPMC_ECC_CTRL_ECCCLEAR 0x100 @@ -936,186 +935,3 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) return 0; } EXPORT_SYMBOL_GPL(gpmc_calculate_ecc); - -#ifdef CONFIG_ARCH_OMAP3 - -/** - * gpmc_init_hwecc_bch - initialize hardware BCH ecc functionality - * @cs: chip select number - * @nsectors: how many 512-byte sectors to process - * @nerrors: how many errors to correct per sector (4 or 8) - * - * This function must be executed before any call to gpmc_enable_hwecc_bch. - */ -int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors) -{ - /* check if ecc module is in use */ - if (gpmc_ecc_used != -EINVAL) - return -EINVAL; - - /* support only OMAP3 class */ - if (!cpu_is_omap34xx()) { - printk(KERN_ERR "BCH ecc is not supported on this CPU\n"); - return -EINVAL; - } - - /* - * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. - * Other chips may be added if confirmed to work. - */ - if ((nerrors == 4) && - (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { - printk(KERN_ERR "BCH 4-bit mode is not supported on this CPU\n"); - return -EINVAL; - } - - /* sanity check */ - if (nsectors > 8) { - printk(KERN_ERR "BCH cannot process %d sectors (max is 8)\n", - nsectors); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch); - -/** - * gpmc_enable_hwecc_bch - enable hardware BCH ecc functionality - * @cs: chip select number - * @mode: read/write mode - * @dev_width: device bus width(1 for x16, 0 for x8) - * @nsectors: how many 512-byte sectors to process - * @nerrors: how many errors to correct per sector (4 or 8) - */ -int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, - int nerrors) -{ - unsigned int val; - - /* check if ecc module is in use */ - if (gpmc_ecc_used != -EINVAL) - return -EINVAL; - - gpmc_ecc_used = cs; - - /* clear ecc and enable bits */ - gpmc_write_reg(GPMC_ECC_CONTROL, 0x1); - - /* - * When using BCH, sector size is hardcoded to 512 bytes. - * Here we are using wrapping mode 6 both for reading and writing, with: - * size0 = 0 (no additional protected byte in spare area) - * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) - */ - gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12)); - - /* BCH configuration */ - val = ((1 << 16) | /* enable BCH */ - (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ - (0x06 << 8) | /* wrap mode = 6 */ - (dev_width << 7) | /* bus width */ - (((nsectors-1) & 0x7) << 4) | /* number of sectors */ - (cs << 1) | /* ECC CS */ - (0x1)); /* enable ECC */ - - gpmc_write_reg(GPMC_ECC_CONFIG, val); - gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch); - -/** - * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes - * @cs: chip select number - * @dat: The pointer to data on which ecc is computed - * @ecc: The ecc output buffer - */ -int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc) -{ - int i; - unsigned long nsectors, reg, val1, val2; - - if (gpmc_ecc_used != cs) - return -EINVAL; - - nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - reg = GPMC_ECC_BCH_RESULT_0 + 16*i; - - /* Read hw-computed remainder */ - val1 = gpmc_read_reg(reg + 0); - val2 = gpmc_read_reg(reg + 4); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs; and - * left-justify the resulting polynomial. - */ - *ecc++ = 0x28 ^ ((val2 >> 12) & 0xFF); - *ecc++ = 0x13 ^ ((val2 >> 4) & 0xFF); - *ecc++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); - *ecc++ = 0x39 ^ ((val1 >> 20) & 0xFF); - *ecc++ = 0x96 ^ ((val1 >> 12) & 0xFF); - *ecc++ = 0xac ^ ((val1 >> 4) & 0xFF); - *ecc++ = 0x7f ^ ((val1 & 0xF) << 4); - } - - gpmc_ecc_used = -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch4); - -/** - * gpmc_calculate_ecc_bch8 - Generate 13 ecc bytes per block of 512 data bytes - * @cs: chip select number - * @dat: The pointer to data on which ecc is computed - * @ecc: The ecc output buffer - */ -int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc) -{ - int i; - unsigned long nsectors, reg, val1, val2, val3, val4; - - if (gpmc_ecc_used != cs) - return -EINVAL; - - nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - reg = GPMC_ECC_BCH_RESULT_0 + 16*i; - - /* Read hw-computed remainder */ - val1 = gpmc_read_reg(reg + 0); - val2 = gpmc_read_reg(reg + 4); - val3 = gpmc_read_reg(reg + 8); - val4 = gpmc_read_reg(reg + 12); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs. - */ - *ecc++ = 0xef ^ (val4 & 0xFF); - *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF); - *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF); - *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF); - *ecc++ = 0xed ^ (val3 & 0xFF); - *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF); - *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF); - *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF); - *ecc++ = 0x97 ^ (val2 & 0xFF); - *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF); - *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF); - *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF); - *ecc++ = 0xb5 ^ (val1 & 0xFF); - } - - gpmc_ecc_used = -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch8); - -#endif /* CONFIG_ARCH_OMAP3 */ diff --git a/trunk/arch/arm/mach-orion5x/ts78xx-setup.c b/trunk/arch/arm/mach-orion5x/ts78xx-setup.c index b4203277f3cd..a74f3cf54cc5 100644 --- a/trunk/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/trunk/arch/arm/mach-orion5x/ts78xx-setup.c @@ -251,6 +251,8 @@ static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd, readsb(io_base, buf, len); } +const char *ts_nand_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition ts78xx_ts_nand_parts[] = { { .name = "mbr", @@ -275,6 +277,7 @@ static struct mtd_partition ts78xx_ts_nand_parts[] = { static struct platform_nand_data ts78xx_ts_nand_data = { .chip = { .nr_chips = 1, + .part_probe_types = ts_nand_part_probes, .partitions = ts78xx_ts_nand_parts, .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), .chip_delay = 15, diff --git a/trunk/arch/arm/mach-pxa/balloon3.c b/trunk/arch/arm/mach-pxa/balloon3.c index 9244493dbcb7..56e8cebeb7d5 100644 --- a/trunk/arch/arm/mach-pxa/balloon3.c +++ b/trunk/arch/arm/mach-pxa/balloon3.c @@ -679,6 +679,8 @@ static struct mtd_partition balloon3_partition_info[] = { }, }; +static const char *balloon3_part_probes[] = { "cmdlinepart", NULL }; + struct platform_nand_data balloon3_nand_pdata = { .chip = { .nr_chips = 4, @@ -686,6 +688,7 @@ struct platform_nand_data balloon3_nand_pdata = { .nr_partitions = ARRAY_SIZE(balloon3_partition_info), .partitions = balloon3_partition_info, .chip_delay = 50, + .part_probe_types = balloon3_part_probes, }, .ctrl = { .hwcontrol = 0, diff --git a/trunk/arch/arm/mach-pxa/em-x270.c b/trunk/arch/arm/mach-pxa/em-x270.c index 97f82ad341bf..a3a4a38d4972 100644 --- a/trunk/arch/arm/mach-pxa/em-x270.c +++ b/trunk/arch/arm/mach-pxa/em-x270.c @@ -338,6 +338,8 @@ static struct mtd_partition em_x270_partition_info[] = { }, }; +static const char *em_x270_part_probes[] = { "cmdlinepart", NULL }; + struct platform_nand_data em_x270_nand_platdata = { .chip = { .nr_chips = 1, @@ -345,6 +347,7 @@ struct platform_nand_data em_x270_nand_platdata = { .nr_partitions = ARRAY_SIZE(em_x270_partition_info), .partitions = em_x270_partition_info, .chip_delay = 20, + .part_probe_types = em_x270_part_probes, }, .ctrl = { .hwcontrol = 0, diff --git a/trunk/arch/arm/mach-pxa/palmtx.c b/trunk/arch/arm/mach-pxa/palmtx.c index 0da35dccfd89..9507605ed547 100644 --- a/trunk/arch/arm/mach-pxa/palmtx.c +++ b/trunk/arch/arm/mach-pxa/palmtx.c @@ -268,6 +268,8 @@ static struct mtd_partition palmtx_partition_info[] = { }, }; +static const char *palmtx_part_probes[] = { "cmdlinepart", NULL }; + struct platform_nand_data palmtx_nand_platdata = { .chip = { .nr_chips = 1, @@ -275,6 +277,7 @@ struct platform_nand_data palmtx_nand_platdata = { .nr_partitions = ARRAY_SIZE(palmtx_partition_info), .partitions = palmtx_partition_info, .chip_delay = 20, + .part_probe_types = palmtx_part_probes, }, .ctrl = { .cmd_ctrl = palmtx_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c b/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c index c3100a044fbe..30a44f806e01 100644 --- a/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -148,25 +148,23 @@ static struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = { static struct s3c_fb_pd_win smdk2416_fb_win[] = { [0] = { + /* think this is the same as the smdk6410 */ + .win_mode = { + .pixclock = 41094, + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .default_bpp = 16, .max_bpp = 32, - .xres = 800, - .yres = 480, }, }; -static struct fb_videomode smdk2416_lcd_timing = { - .pixclock = 41094, - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - static void s3c2416_fb_gpio_setup_24bpp(void) { unsigned int gpio; @@ -189,7 +187,6 @@ static void s3c2416_fb_gpio_setup_24bpp(void) static struct s3c_fb_platdata smdk2416_fb_platdata = { .win[0] = &smdk2416_fb_win[0], - .vtiming = &smdk2416_lcd_timing, .setup_gpio = s3c2416_fb_gpio_setup_24bpp, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c b/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c index ffa29ddfdfce..314df0518afd 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c @@ -134,27 +134,24 @@ static struct platform_device anw6410_lcd_powerdev = { }; static struct s3c_fb_pd_win anw6410_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode anw6410_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &anw6410_lcd_timing, .win[0] = &anw6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c b/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c index d0c352d861f8..6b20a71d7dbf 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -151,29 +151,26 @@ static struct platform_device crag6410_lcd_powerdev = { /* 640x480 URT */ static struct s3c_fb_pd_win crag6410_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 150, + .right_margin = 80, + .upper_margin = 40, + .lower_margin = 5, + .hsync_len = 40, + .vsync_len = 5, + .xres = 640, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 640, - .yres = 480, .virtual_y = 480 * 2, .virtual_x = 640, }; -static struct fb_videomode crag6410_lcd_timing = { - .left_margin = 150, - .right_margin = 80, - .upper_margin = 40, - .lower_margin = 5, - .hsync_len = 40, - .vsync_len = 5, - .xres = 640, - .yres = 480, -}; - /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &crag6410_lcd_timing, .win[0] = &crag6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-hmt.c b/trunk/arch/arm/mach-s3c64xx/mach-hmt.c index 689088162f77..1bf6b9da20fc 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-hmt.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-hmt.c @@ -129,27 +129,23 @@ static struct platform_device hmt_backlight_device = { }; static struct s3c_fb_pd_win hmt_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode hmt_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata hmt_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &hmt_lcd_timing, .win[0] = &hmt_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c b/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c index 5539a255a704..f8ea61ea3b33 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c @@ -140,59 +140,41 @@ static struct s3c2410_platform_nand mini6410_nand_info = { .sets = mini6410_nand_sets, }; -static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 480, - .yres = 272, -}; - -static struct fb_videomode mini6410_lcd_type0_timing = { - /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, - .xres = 480, - .yres = 272, -}; - -static struct s3c_fb_pd_win mini6410_lcd_type1_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode mini6410_lcd_type1_timing = { - /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - -static struct s3c_fb_platdata mini6410_lcd_pdata[] __initdata = { +static struct s3c_fb_pd_win mini6410_fb_win[] = { { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &mini6410_lcd_type0_timing, - .win[0] = &mini6410_lcd_type0_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, + .xres = 480, + .yres = 272, + }, + .max_bpp = 32, + .default_bpp = 16, }, { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &mini6410_lcd_type1_timing, - .win[0] = &mini6410_lcd_type1_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, }, - { }, +}; + +static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &mini6410_fb_win[0], + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, }; static void mini6410_lcd_power_set(struct plat_lcd_data *pd, @@ -290,7 +272,7 @@ static void mini6410_parse_features( "screen type already set\n", f); } else { int li = f - '0'; - if (li >= ARRAY_SIZE(mini6410_lcd_pdata)) + if (li >= ARRAY_SIZE(mini6410_fb_win)) printk(KERN_INFO "MINI6410: '%c' out " "of range LCD mode\n", f); else { @@ -314,12 +296,14 @@ static void __init mini6410_machine_init(void) /* Parse the feature string */ mini6410_parse_features(&features, mini6410_features_str); + mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index]; + printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n", - mini6410_lcd_pdata[features.lcd_index].win[0]->xres, - mini6410_lcd_pdata[features.lcd_index].win[0]->yres); + mini6410_lcd_pdata.win[0]->win_mode.xres, + mini6410_lcd_pdata.win[0]->win_mode.yres); s3c_nand_set_platdata(&mini6410_nand_info); - s3c_fb_set_platdata(&mini6410_lcd_pdata[features.lcd_index]); + s3c_fb_set_platdata(&mini6410_lcd_pdata); s3c24xx_ts_set_platdata(NULL); /* configure nCS1 width to 16 bits */ diff --git a/trunk/arch/arm/mach-s3c64xx/mach-real6410.c b/trunk/arch/arm/mach-s3c64xx/mach-real6410.c index 326b21604bc3..b92d8e17d502 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-real6410.c @@ -106,57 +106,41 @@ static struct platform_device real6410_device_eth = { }, }; -static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 480, - .yres = 272, -}; - -static struct fb_videomode real6410_lcd_type0_timing = { - /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, -}; - -static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode real6410_lcd_type1_timing = { - /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - -static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = { +static struct s3c_fb_pd_win real6410_fb_win[] = { { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &real6410_lcd_type0_timing, - .win[0] = &real6410_lcd_type0_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, + .xres = 480, + .yres = 272, + }, + .max_bpp = 32, + .default_bpp = 16, }, { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &real6410_lcd_type1_timing, - .win[0] = &real6410_lcd_type1_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, }, - { }, +}; + +static struct s3c_fb_platdata real6410_lcd_pdata __initdata = { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &real6410_fb_win[0], + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, }; static struct mtd_partition real6410_nand_part[] = { @@ -269,7 +253,7 @@ static void real6410_parse_features( "screen type already set\n", f); } else { int li = f - '0'; - if (li >= ARRAY_SIZE(real6410_lcd_pdata)) + if (li >= ARRAY_SIZE(real6410_fb_win)) printk(KERN_INFO "REAL6410: '%c' out " "of range LCD mode\n", f); else { @@ -293,11 +277,13 @@ static void __init real6410_machine_init(void) /* Parse the feature string */ real6410_parse_features(&features, real6410_features_str); + real6410_lcd_pdata.win[0] = &real6410_fb_win[features.lcd_index]; + printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n", - real6410_lcd_pdata[features.lcd_index].win[0]->xres, - real6410_lcd_pdata[features.lcd_index].win[0]->yres); + real6410_lcd_pdata.win[0]->win_mode.xres, + real6410_lcd_pdata.win[0]->win_mode.yres); - s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]); + s3c_fb_set_platdata(&real6410_lcd_pdata); s3c_nand_set_platdata(&real6410_nand_info); s3c24xx_ts_set_platdata(NULL); diff --git a/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c b/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c index d6266d8b43c9..c5021d0335c6 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -108,27 +108,23 @@ static struct platform_device smartq5_buttons_device = { }; static struct s3c_fb_pd_win smartq5_fb_win0 = { + .win_mode = { + .left_margin = 216, + .right_margin = 40, + .upper_margin = 35, + .lower_margin = 10, + .hsync_len = 1, + .vsync_len = 1, + .xres = 800, + .yres = 480, + .refresh = 80, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smartq5_lcd_timing = { - .left_margin = 216, - .right_margin = 40, - .upper_margin = 35, - .lower_margin = 10, - .hsync_len = 1, - .vsync_len = 1, - .xres = 800, - .yres = 480, - .refresh = 80, }; static struct s3c_fb_platdata smartq5_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &smartq5_lcd_timing, .win[0] = &smartq5_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | diff --git a/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c b/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c index 0957d2a980e1..aa9072a4cbef 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c @@ -124,27 +124,23 @@ static struct platform_device smartq7_buttons_device = { }; static struct s3c_fb_pd_win smartq7_fb_win0 = { + .win_mode = { + .left_margin = 3, + .right_margin = 5, + .upper_margin = 1, + .lower_margin = 20, + .hsync_len = 10, + .vsync_len = 3, + .xres = 800, + .yres = 480, + .refresh = 80, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smartq7_lcd_timing = { - .left_margin = 3, - .right_margin = 5, - .upper_margin = 1, - .lower_margin = 20, - .hsync_len = 10, - .vsync_len = 3, - .xres = 800, - .yres = 480, - .refresh = 80, }; static struct s3c_fb_platdata smartq7_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &smartq7_lcd_timing, .win[0] = &smartq7_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | diff --git a/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c b/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c index df3103d450e2..d44319b09412 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -146,29 +146,26 @@ static struct platform_device smdk6410_lcd_powerdev = { }; static struct s3c_fb_pd_win smdk6410_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, .virtual_y = 480 * 2, .virtual_x = 800, }; -static struct fb_videomode smdk6410_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &smdk6410_lcd_timing, .win[0] = &smdk6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c b/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c index 92fefad505cc..a40e325d62c8 100644 --- a/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -103,26 +103,22 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win smdk6440_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdk6440_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = { .win[0] = &smdk6440_fb_win0, - .vtiming = &smdk6440_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c b/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c index e2335ecf6eae..efb69e2f2afe 100644 --- a/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -121,26 +121,22 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win smdk6450_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdk6450_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = { .win[0] = &smdk6450_fb_win0, - .vtiming = &smdk6450_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c b/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c index 0c3ae38d27ca..674d22992f3c 100644 --- a/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -136,27 +136,24 @@ static struct platform_device smdkc100_lcd_powerdev = { /* Frame Buffer */ static struct s3c_fb_pd_win smdkc100_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + .refresh = 80, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdkc100_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - .refresh = 80, }; static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = { .win[0] = &smdkc100_fb_win0, - .vtiming = &smdkc100_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5pc100_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-s5pv210/mach-aquila.c b/trunk/arch/arm/mach-s5pv210/mach-aquila.c index af528f9e97f9..48d018f2332b 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-aquila.c +++ b/trunk/arch/arm/mach-s5pv210/mach-aquila.c @@ -96,34 +96,38 @@ static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win aquila_fb_win0 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 3, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 2, + .xres = 480, + .yres = 800, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, }; static struct s3c_fb_pd_win aquila_fb_win1 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 3, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 2, + .xres = 480, + .yres = 800, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, -}; - -static struct fb_videomode aquila_lcd_timing = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 3, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 2, - .xres = 480, - .yres = 800, }; static struct s3c_fb_platdata aquila_lcd_pdata __initdata = { .win[0] = &aquila_fb_win0, .win[1] = &aquila_fb_win1, - .vtiming = &aquila_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | VIDCON1_INV_VCLK | VIDCON1_INV_VDEN, diff --git a/trunk/arch/arm/mach-s5pv210/mach-goni.c b/trunk/arch/arm/mach-s5pv210/mach-goni.c index bf5087c2b7fe..f20a97c8e411 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-goni.c +++ b/trunk/arch/arm/mach-s5pv210/mach-goni.c @@ -107,29 +107,25 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win goni_fb_win0 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 2, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 1, + .xres = 480, + .yres = 800, + .refresh = 55, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, .virtual_x = 480, .virtual_y = 2 * 800, }; -static struct fb_videomode goni_lcd_timing = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 1, - .xres = 480, - .yres = 800, - .refresh = 55, -}; - static struct s3c_fb_platdata goni_lcd_pdata __initdata = { .win[0] = &goni_fb_win0, - .vtiming = &goni_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN diff --git a/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c b/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c index 0d7ddec88eb7..fa1b61209fd9 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -178,26 +178,22 @@ static struct platform_device smdkv210_lcd_lte480wv = { }; static struct s3c_fb_pd_win smdkv210_fb_win0 = { + .win_mode = { + .left_margin = 13, + .right_margin = 8, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdkv210_lcd_timing = { - .left_margin = 13, - .right_margin = 8, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = { .win[0] = &smdkv210_fb_win0, - .vtiming = &smdkv210_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5pv210_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-ux500/board-mop500-uib.c b/trunk/arch/arm/mach-ux500/board-mop500-uib.c index 1f47d962e3a1..b29a788f498c 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500-uib.c +++ b/trunk/arch/arm/mach-ux500/board-mop500-uib.c @@ -96,7 +96,7 @@ static void __init __mop500_uib_init(struct uib *uib, const char *why) /* * Detect the UIB attached based on the presence or absence of i2c devices. */ -int __init mop500_uib_init(void) +static int __init mop500_uib_init(void) { struct uib *uib = mop500_uib; struct i2c_adapter *i2c0; @@ -131,3 +131,5 @@ int __init mop500_uib_init(void) return 0; } + +module_init(mop500_uib_init); diff --git a/trunk/arch/arm/mach-ux500/board-mop500.c b/trunk/arch/arm/mach-ux500/board-mop500.c index 9c74ac545849..fba8adea421e 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500.c +++ b/trunk/arch/arm/mach-ux500/board-mop500.c @@ -673,15 +673,9 @@ static void __init u8500_cryp1_hash1_init(struct device *parent) static struct platform_device *snowball_platform_devs[] __initdata = { &snowball_led_dev, &snowball_key_dev, - &snowball_sbnet_dev, &ab8500_device, }; -static struct platform_device *snowball_of_platform_devs[] __initdata = { - &snowball_led_dev, - &snowball_key_dev, -}; - static void __init mop500_init_machine(void) { struct device *parent = NULL; @@ -716,8 +710,6 @@ static void __init mop500_init_machine(void) /* This board has full regulator constraints */ regulator_has_full_constraints(); - - mop500_uib_init(); } static void __init snowball_init_machine(void) @@ -782,8 +774,6 @@ static void __init hrefv60_init_machine(void) /* This board has full regulator constraints */ regulator_has_full_constraints(); - - mop500_uib_init(); } MACHINE_START(U8500, "ST-Ericsson MOP500 platform") @@ -844,10 +834,6 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { static const struct of_device_id u8500_local_bus_nodes[] = { /* only create devices below soc node */ { .compatible = "stericsson,db8500", }, - { .compatible = "stericsson,db8500-prcmu", }, - { .compatible = "stericsson,db8500-prcmu-regulator", }, - { .compatible = "stericsson,ab8500", }, - { .compatible = "stericsson,ab8500-regulator", }, { .compatible = "simple-bus"}, { }, }; @@ -866,7 +852,7 @@ static void __init u8500_init_machine(void) else if (of_machine_is_compatible("st-ericsson,hrefv60+")) hrefv60_pinmaps_init(); - parent = u8500_of_init_devices(); + parent = u8500_init_devices(); for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; @@ -883,23 +869,15 @@ static void __init u8500_init_machine(void) ARRAY_SIZE(mop500_platform_devs)); mop500_sdi_init(parent); + i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, ARRAY_SIZE(mop500_i2c2_devices)); - mop500_uib_init(); - } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { - /* - * Devices to be DT:ed: - * snowball_led_dev = todo - * snowball_key_dev = todo - * snowball_sbnet_dev = done - * ab8500_device = done - */ - platform_add_devices(snowball_of_platform_devs, - ARRAY_SIZE(snowball_of_platform_devs)); + platform_add_devices(snowball_platform_devs, + ARRAY_SIZE(snowball_platform_devs)); snowball_sdi_init(parent); } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) { @@ -920,8 +898,6 @@ static void __init u8500_init_machine(void) i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, ARRAY_SIZE(mop500_i2c2_devices)); - - mop500_uib_init(); } mop500_i2c_init(parent); diff --git a/trunk/arch/arm/mach-ux500/board-mop500.h b/trunk/arch/arm/mach-ux500/board-mop500.h index 2f87b25a908a..bc44c07c71a9 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500.h +++ b/trunk/arch/arm/mach-ux500/board-mop500.h @@ -89,11 +89,7 @@ void __init mop500_pinmaps_init(void); void __init snowball_pinmaps_init(void); void __init hrefv60_pinmaps_init(void); -int __init mop500_uib_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, unsigned n); -/* TODO: Once all pieces are DT:ed, remove completely. */ -struct device * __init u8500_of_init_devices(void); - #endif diff --git a/trunk/arch/arm/mach-ux500/cpu-db8500.c b/trunk/arch/arm/mach-ux500/cpu-db8500.c index 33275eb4c689..16169c4bf6ca 100644 --- a/trunk/arch/arm/mach-ux500/cpu-db8500.c +++ b/trunk/arch/arm/mach-ux500/cpu-db8500.c @@ -140,6 +140,7 @@ static struct platform_device *platform_devs[] __initdata = { static struct platform_device *of_platform_devs[] __initdata = { &u8500_dma40_device, &db8500_pmu_device, + &db8500_prcmu_device, }; static resource_size_t __initdata db8500_gpio_base[] = { @@ -218,28 +219,6 @@ struct device * __init u8500_init_devices(void) db8500_add_gpios(parent); db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); - platform_device_register_data(parent, - "cpufreq-u8500", -1, NULL, 0); - - for (i = 0; i < ARRAY_SIZE(platform_devs); i++) - platform_devs[i]->dev.parent = parent; - - platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); - - return parent; -} - -/* TODO: Once all pieces are DT:ed, remove completely. */ -struct device * __init u8500_of_init_devices(void) -{ - struct device *parent; - int i; - - parent = db8500_soc_device_init(); - - db8500_add_rtc(parent); - db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); - platform_device_register_data(parent, "cpufreq-u8500", -1, NULL, 0); @@ -250,7 +229,7 @@ struct device * __init u8500_of_init_devices(void) * Devices to be DT:ed: * u8500_dma40_device = todo * db8500_pmu_device = todo - * db8500_prcmu_device = done + * db8500_prcmu_device = todo */ platform_add_devices(of_platform_devs, ARRAY_SIZE(of_platform_devs)); diff --git a/trunk/arch/arm/plat-omap/include/plat/gpmc.h b/trunk/arch/arm/plat-omap/include/plat/gpmc.h index f37764a36072..1527929b445a 100644 --- a/trunk/arch/arm/plat-omap/include/plat/gpmc.h +++ b/trunk/arch/arm/plat-omap/include/plat/gpmc.h @@ -92,8 +92,6 @@ enum omap_ecc { OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ /* 1-bit ecc: stored at beginning of spare area as romcode */ OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ - OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */ - OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */ }; /* @@ -159,13 +157,4 @@ extern int gpmc_nand_write(int cs, int cmd, int wval); int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size); int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); - -#ifdef CONFIG_ARCH_OMAP3 -int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors); -int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, - int nerrors); -int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc); -int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc); -#endif /* CONFIG_ARCH_OMAP3 */ - #endif diff --git a/trunk/arch/arm/plat-samsung/include/plat/fb.h b/trunk/arch/arm/plat-samsung/include/plat/fb.h index 536002ff2ab8..0fedf47fa502 100644 --- a/trunk/arch/arm/plat-samsung/include/plat/fb.h +++ b/trunk/arch/arm/plat-samsung/include/plat/fb.h @@ -24,16 +24,15 @@ /** * struct s3c_fb_pd_win - per window setup data - * @xres : The window X size. - * @yres : The window Y size. + * @win_mode: The display parameters to initialise (not for window 0) * @virtual_x: The virtual X size. * @virtual_y: The virtual Y size. */ struct s3c_fb_pd_win { + struct fb_videomode win_mode; + unsigned short default_bpp; unsigned short max_bpp; - unsigned short xres; - unsigned short yres; unsigned short virtual_x; unsigned short virtual_y; }; @@ -46,7 +45,6 @@ struct s3c_fb_pd_win { * @default_win: default window layer number to be used for UI layer. * @vidcon0: The base vidcon0 values to control the panel data format. * @vidcon1: The base vidcon1 values to control the panel data output. - * @vtiming: Video timing when connected to a RGB type panel. * @win: The setup data for each hardware window, or NULL for unused. * @display_mode: The LCD output display mode. * @@ -60,7 +58,8 @@ struct s3c_fb_platdata { void (*setup_gpio)(void); struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; - struct fb_videomode *vtiming; + + u32 default_win; u32 vidcon0; u32 vidcon1; diff --git a/trunk/arch/blackfin/mach-bf561/boards/acvilon.c b/trunk/arch/blackfin/mach-bf561/boards/acvilon.c index 0b74218fdd3a..f6ffd6f054c3 100644 --- a/trunk/arch/blackfin/mach-bf561/boards/acvilon.c +++ b/trunk/arch/blackfin/mach-bf561/boards/acvilon.c @@ -248,6 +248,8 @@ static struct platform_device bfin_uart0_device = { #if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) +const char *part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition bfin_plat_nand_partitions[] = { { .name = "params(nand)", @@ -287,6 +289,7 @@ static struct platform_nand_data bfin_plat_nand_data = { .chip = { .nr_chips = 1, .chip_delay = 30, + .part_probe_types = part_probes, .partitions = bfin_plat_nand_partitions, .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions), }, diff --git a/trunk/arch/mips/alchemy/devboards/db1200.c b/trunk/arch/mips/alchemy/devboards/db1200.c index bf2248474fa8..7dde01642d6b 100644 --- a/trunk/arch/mips/alchemy/devboards/db1200.c +++ b/trunk/arch/mips/alchemy/devboards/db1200.c @@ -213,6 +213,8 @@ static int au1200_nand_device_ready(struct mtd_info *mtd) return __raw_readl((void __iomem *)MEM_STSTAT) & 1; } +static const char *db1200_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition db1200_nand_parts[] = { { .name = "NAND FS 0", @@ -233,6 +235,7 @@ struct platform_nand_data db1200_nand_platdata = { .nr_partitions = ARRAY_SIZE(db1200_nand_parts), .partitions = db1200_nand_parts, .chip_delay = 20, + .part_probe_types = db1200_part_probes, }, .ctrl = { .dev_ready = au1200_nand_device_ready, diff --git a/trunk/arch/mips/alchemy/devboards/db1300.c b/trunk/arch/mips/alchemy/devboards/db1300.c index c56e0246694e..0893f2af0d01 100644 --- a/trunk/arch/mips/alchemy/devboards/db1300.c +++ b/trunk/arch/mips/alchemy/devboards/db1300.c @@ -145,6 +145,8 @@ static int au1300_nand_device_ready(struct mtd_info *mtd) return __raw_readl((void __iomem *)MEM_STSTAT) & 1; } +static const char *db1300_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition db1300_nand_parts[] = { { .name = "NAND FS 0", @@ -165,6 +167,7 @@ struct platform_nand_data db1300_nand_platdata = { .nr_partitions = ARRAY_SIZE(db1300_nand_parts), .partitions = db1300_nand_parts, .chip_delay = 20, + .part_probe_types = db1300_part_probes, }, .ctrl = { .dev_ready = au1300_nand_device_ready, diff --git a/trunk/arch/mips/alchemy/devboards/db1550.c b/trunk/arch/mips/alchemy/devboards/db1550.c index 9eb79062f46e..6815d0783cd8 100644 --- a/trunk/arch/mips/alchemy/devboards/db1550.c +++ b/trunk/arch/mips/alchemy/devboards/db1550.c @@ -149,6 +149,8 @@ static int au1550_nand_device_ready(struct mtd_info *mtd) return __raw_readl((void __iomem *)MEM_STSTAT) & 1; } +static const char *db1550_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition db1550_nand_parts[] = { { .name = "NAND FS 0", @@ -169,6 +171,7 @@ struct platform_nand_data db1550_nand_platdata = { .nr_partitions = ARRAY_SIZE(db1550_nand_parts), .partitions = db1550_nand_parts, .chip_delay = 20, + .part_probe_types = db1550_part_probes, }, .ctrl = { .dev_ready = au1550_nand_device_ready, diff --git a/trunk/arch/mips/pnx833x/common/platform.c b/trunk/arch/mips/pnx833x/common/platform.c index 05a1d922cd60..87167dcc79fa 100644 --- a/trunk/arch/mips/pnx833x/common/platform.c +++ b/trunk/arch/mips/pnx833x/common/platform.c @@ -244,6 +244,11 @@ static struct platform_device pnx833x_sata_device = { .resource = pnx833x_sata_resources, }; +static const char *part_probes[] = { + "cmdlinepart", + NULL +}; + static void pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { @@ -263,6 +268,7 @@ static struct platform_nand_data pnx833x_flash_nand_data = { .chip = { .nr_chips = 1, .chip_delay = 25, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl diff --git a/trunk/arch/mips/rb532/devices.c b/trunk/arch/mips/rb532/devices.c index 716e9a12f0e7..ea774285e6c5 100644 --- a/trunk/arch/mips/rb532/devices.c +++ b/trunk/arch/mips/rb532/devices.c @@ -293,6 +293,7 @@ static void __init rb532_nand_setup(void) rb532_nand_data.chip.nr_partitions = ARRAY_SIZE(rb532_partition_info); rb532_nand_data.chip.partitions = rb532_partition_info; rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY; + rb532_nand_data.chip.options = NAND_NO_AUTOINCR; } diff --git a/trunk/arch/powerpc/include/asm/stat.h b/trunk/arch/powerpc/include/asm/stat.h index 10cfb558e0fd..84880b80cc1c 100644 --- a/trunk/arch/powerpc/include/asm/stat.h +++ b/trunk/arch/powerpc/include/asm/stat.h @@ -30,7 +30,7 @@ struct stat { unsigned long st_dev; ino_t st_ino; #ifdef __powerpc64__ - unsigned short st_nlink; + unsigned long st_nlink; mode_t st_mode; #else mode_t st_mode; diff --git a/trunk/arch/sh/boards/mach-migor/setup.c b/trunk/arch/sh/boards/mach-migor/setup.c index a8a1ca741c85..34cd0c5ff2e1 100644 --- a/trunk/arch/sh/boards/mach-migor/setup.c +++ b/trunk/arch/sh/boards/mach-migor/setup.c @@ -188,6 +188,7 @@ static struct platform_nand_data migor_nand_flash_data = { .partitions = migor_nand_flash_partitions, .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions), .chip_delay = 20, + .part_probe_types = (const char *[]) { "cmdlinepart", NULL }, }, .ctrl = { .dev_ready = migor_nand_flash_ready, diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c index 7053140c6596..d7038230b71e 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -35,28 +35,9 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { {0,} }; - -static void cirrus_kick_out_firmware_fb(struct pci_dev *pdev) -{ - struct apertures_struct *ap; - bool primary = false; - - ap = alloc_apertures(1); - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); - -#ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; -#endif - remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary); - kfree(ap); -} - static int __devinit cirrus_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - cirrus_kick_out_firmware_fb(pdev); - return drm_get_pci_dev(pdev, ent, &driver); } diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h index 64ea597cb6d3..21bdfa8836f7 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -145,7 +145,7 @@ struct cirrus_device { struct ttm_bo_device bdev; atomic_t validate_sequence; } ttm; - bool mm_inited; + }; diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c b/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c index 50e170f879de..2ebcd11a5023 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -275,17 +275,12 @@ int cirrus_mm_init(struct cirrus_device *cirrus) pci_resource_len(dev->pdev, 0), DRM_MTRR_WC); - cirrus->mm_inited = true; return 0; } void cirrus_mm_fini(struct cirrus_device *cirrus) { struct drm_device *dev = cirrus->dev; - - if (!cirrus->mm_inited) - return; - ttm_bo_device_release(&cirrus->ttm.bdev); cirrus_ttm_global_release(cirrus); diff --git a/trunk/drivers/gpu/drm/drm_edid.c b/trunk/drivers/gpu/drm/drm_edid.c index eb92fe257a39..c3b5139eba7f 100644 --- a/trunk/drivers/gpu/drm/drm_edid.c +++ b/trunk/drivers/gpu/drm/drm_edid.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "drmP.h" #include "drm_edid.h" #include "drm_edid_modes.h" @@ -149,10 +149,6 @@ int drm_edid_header_is_valid(const u8 *raw_edid) } EXPORT_SYMBOL(drm_edid_header_is_valid); -static int edid_fixup __read_mostly = 6; -module_param_named(edid_fixup, edid_fixup, int, 0400); -MODULE_PARM_DESC(edid_fixup, - "Minimum number of valid EDID header bytes (0-8, default 6)"); /* * Sanity check the EDID block (base or extension). Return 0 if the block @@ -164,13 +160,10 @@ bool drm_edid_block_valid(u8 *raw_edid, int block) u8 csum = 0; struct edid *edid = (struct edid *)raw_edid; - if (edid_fixup > 8 || edid_fixup < 0) - edid_fixup = 6; - if (block == 0) { int score = drm_edid_header_is_valid(raw_edid); if (score == 8) ; - else if (score >= edid_fixup) { + else if (score >= 6) { DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); memcpy(raw_edid, edid_header, sizeof(edid_header)); } else { diff --git a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c index 93e832d6c328..3c8e04f54713 100644 --- a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -41,28 +41,9 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { MODULE_DEVICE_TABLE(pci, pciidlist); -static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev) -{ - struct apertures_struct *ap; - bool primary = false; - - ap = alloc_apertures(1); - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); - -#ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; -#endif - remove_conflicting_framebuffers(ap, "mgag200drmfb", primary); - kfree(ap); -} - - static int __devinit mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - mgag200_kick_out_firmware_fb(pdev); - return drm_get_pci_dev(pdev, ent, &driver); } diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index 01550d05e273..58991af90502 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -1029,11 +1029,6 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); - if ((rdev->family == CHIP_JUNIPER) || - (rdev->family == CHIP_CYPRESS) || - (rdev->family == CHIP_HEMLOCK) || - (rdev->family == CHIP_BARTS)) - WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); } WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); @@ -1558,10 +1553,163 @@ int evergreen_cp_resume(struct radeon_device *rdev) /* * Core functions */ +static u32 evergreen_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask = 0; + u32 enabled_backends_count = 0; + u32 cur_pipe; + u32 swizzle_pipe[EVERGREEN_MAX_PIPES]; + u32 cur_backend = 0; + u32 i; + bool force_no_swizzle; + + if (num_tile_pipes > EVERGREEN_MAX_PIPES) + num_tile_pipes = EVERGREEN_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > EVERGREEN_MAX_BACKENDS) + num_backends = EVERGREEN_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + for (i = 0; i < EVERGREEN_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * EVERGREEN_MAX_PIPES); + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: + case CHIP_TURKS: + case CHIP_CAICOS: + force_no_swizzle = false; + break; + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + case CHIP_JUNIPER: + case CHIP_BARTS: + default: + force_no_swizzle = true; + break; + } + if (force_no_swizzle) { + bool last_backend_enabled = false; + + force_no_swizzle = false; + for (i = 0; i < EVERGREEN_MAX_BACKENDS; ++i) { + if (((enabled_backends_mask >> i) & 1) == 1) { + if (last_backend_enabled) + force_no_swizzle = true; + last_backend_enabled = true; + } else + last_backend_enabled = false; + } + } + + switch (num_tile_pipes) { + case 1: + case 3: + case 5: + case 7: + DRM_ERROR("odd number of pipes!\n"); + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + swizzle_pipe[3] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + } + break; + } + + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % EVERGREEN_MAX_BACKENDS; + + backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); + + cur_backend = (cur_backend + 1) % EVERGREEN_MAX_BACKENDS; + } + + return backend_map; +} + static void evergreen_gpu_init(struct radeon_device *rdev) { - u32 gb_addr_config; + u32 cc_rb_backend_disable = 0; + u32 cc_gc_shader_pipe_config; + u32 gb_addr_config = 0; u32 mc_shared_chmap, mc_arb_ramcfg; + u32 gb_backend_map; + u32 grbm_gfx_index; u32 sx_debug_1; u32 smx_dc_ctl0; u32 sq_config; @@ -1576,7 +1724,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) u32 sq_stack_resource_mgmt_3; u32 vgt_cache_invalidation; u32 hdp_host_path_cntl, tmp; - u32 disabled_rb_mask; int i, j, num_shader_engines, ps_thread_count; switch (rdev->family) { @@ -1601,7 +1748,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CYPRESS_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_JUNIPER: rdev->config.evergreen.num_ses = 1; @@ -1623,7 +1769,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = JUNIPER_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_REDWOOD: rdev->config.evergreen.num_ses = 1; @@ -1645,7 +1790,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_CEDAR: default: @@ -1668,7 +1812,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_PALM: rdev->config.evergreen.num_ses = 1; @@ -1690,7 +1833,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_SUMO: rdev->config.evergreen.num_ses = 1; @@ -1718,7 +1860,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_SUMO2: rdev->config.evergreen.num_ses = 1; @@ -1740,7 +1881,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_BARTS: rdev->config.evergreen.num_ses = 2; @@ -1762,7 +1902,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = BARTS_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_TURKS: rdev->config.evergreen.num_ses = 1; @@ -1784,7 +1923,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = TURKS_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_CAICOS: rdev->config.evergreen.num_ses = 1; @@ -1806,7 +1944,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CAICOS_GB_ADDR_CONFIG_GOLDEN; break; } @@ -1823,6 +1960,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev) evergreen_fix_pci_max_read_req_size(rdev); + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & ~2; + + cc_gc_shader_pipe_config |= + INACTIVE_QD_PIPES((EVERGREEN_MAX_PIPES_MASK << rdev->config.evergreen.max_pipes) + & EVERGREEN_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + INACTIVE_SIMDS((EVERGREEN_MAX_SIMDS_MASK << rdev->config.evergreen.max_simds) + & EVERGREEN_MAX_SIMDS_MASK); + + cc_rb_backend_disable = + BACKEND_DISABLE((EVERGREEN_MAX_BACKENDS_MASK << rdev->config.evergreen.max_backends) + & EVERGREEN_MAX_BACKENDS_MASK); + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); if ((rdev->family == CHIP_PALM) || (rdev->family == CHIP_SUMO) || @@ -1831,6 +1982,134 @@ static void evergreen_gpu_init(struct radeon_device *rdev) else mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + switch (rdev->config.evergreen.max_tile_pipes) { + case 1: + default: + gb_addr_config |= NUM_PIPES(0); + break; + case 2: + gb_addr_config |= NUM_PIPES(1); + break; + case 4: + gb_addr_config |= NUM_PIPES(2); + break; + case 8: + gb_addr_config |= NUM_PIPES(3); + break; + } + + gb_addr_config |= PIPE_INTERLEAVE_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + gb_addr_config |= BANK_INTERLEAVE_SIZE(0); + gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.evergreen.num_ses - 1); + gb_addr_config |= SHADER_ENGINE_TILE_SIZE(1); + gb_addr_config |= NUM_GPUS(0); /* Hemlock? */ + gb_addr_config |= MULTI_GPU_TILE_SIZE(2); + + if (((mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) > 2) + gb_addr_config |= ROW_SIZE(2); + else + gb_addr_config |= ROW_SIZE((mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT); + + if (rdev->ddev->pdev->device == 0x689e) { + u32 efuse_straps_4; + u32 efuse_straps_3; + u8 efuse_box_bit_131_124; + + WREG32(RCU_IND_INDEX, 0x204); + efuse_straps_4 = RREG32(RCU_IND_DATA); + WREG32(RCU_IND_INDEX, 0x203); + efuse_straps_3 = RREG32(RCU_IND_DATA); + efuse_box_bit_131_124 = (u8)(((efuse_straps_4 & 0xf) << 4) | ((efuse_straps_3 & 0xf0000000) >> 28)); + + switch(efuse_box_bit_131_124) { + case 0x00: + gb_backend_map = 0x76543210; + break; + case 0x55: + gb_backend_map = 0x77553311; + break; + case 0x56: + gb_backend_map = 0x77553300; + break; + case 0x59: + gb_backend_map = 0x77552211; + break; + case 0x66: + gb_backend_map = 0x77443300; + break; + case 0x99: + gb_backend_map = 0x66552211; + break; + case 0x5a: + gb_backend_map = 0x77552200; + break; + case 0xaa: + gb_backend_map = 0x66442200; + break; + case 0x95: + gb_backend_map = 0x66553311; + break; + default: + DRM_ERROR("bad backend map, using default\n"); + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + break; + } + } else if (rdev->ddev->pdev->device == 0x68b9) { + u32 efuse_straps_3; + u8 efuse_box_bit_127_124; + + WREG32(RCU_IND_INDEX, 0x203); + efuse_straps_3 = RREG32(RCU_IND_DATA); + efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28); + + switch(efuse_box_bit_127_124) { + case 0x0: + gb_backend_map = 0x00003210; + break; + case 0x5: + case 0x6: + case 0x9: + case 0xa: + gb_backend_map = 0x00003311; + break; + default: + DRM_ERROR("bad backend map, using default\n"); + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + break; + } + } else { + switch (rdev->family) { + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + case CHIP_BARTS: + gb_backend_map = 0x66442200; + break; + case CHIP_JUNIPER: + gb_backend_map = 0x00002200; + break; + default: + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + } + } + /* setup tiling info dword. gb_addr_config is not adequate since it does * not have bank info, so create a custom tiling dword. * bits 3:0 num_pipes @@ -1857,54 +2136,45 @@ static void evergreen_gpu_init(struct radeon_device *rdev) /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ if (rdev->flags & RADEON_IS_IGP) rdev->config.evergreen.tile_config |= 1 << 4; - else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.evergreen.tile_config |= 1 << 4; - else - rdev->config.evergreen.tile_config |= 0 << 4; - } - rdev->config.evergreen.tile_config |= 0 << 8; + else + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; rdev->config.evergreen.tile_config |= ((gb_addr_config & 0x30000000) >> 28) << 12; - num_shader_engines = (gb_addr_config & NUM_SHADER_ENGINES(3) >> 12) + 1; + rdev->config.evergreen.backend_map = gb_backend_map; + WREG32(GB_BACKEND_MAP, gb_backend_map); + WREG32(GB_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + WREG32(HDP_ADDR_CONFIG, gb_addr_config); - if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) { - u32 efuse_straps_4; - u32 efuse_straps_3; + num_shader_engines = ((RREG32(GB_ADDR_CONFIG) & NUM_SHADER_ENGINES(3)) >> 12) + 1; + grbm_gfx_index = INSTANCE_BROADCAST_WRITES; - WREG32(RCU_IND_INDEX, 0x204); - efuse_straps_4 = RREG32(RCU_IND_DATA); - WREG32(RCU_IND_INDEX, 0x203); - efuse_straps_3 = RREG32(RCU_IND_DATA); - tmp = (((efuse_straps_4 & 0xf) << 4) | - ((efuse_straps_3 & 0xf0000000) >> 28)); - } else { - tmp = 0; - for (i = (rdev->config.evergreen.num_ses - 1); i >= 0; i--) { - u32 rb_disable_bitmap; - - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; - tmp <<= 4; - tmp |= rb_disable_bitmap; + for (i = 0; i < rdev->config.evergreen.num_ses; i++) { + u32 rb = cc_rb_backend_disable | (0xf0 << 16); + u32 sp = cc_gc_shader_pipe_config; + u32 gfx = grbm_gfx_index | SE_INDEX(i); + + if (i == num_shader_engines) { + rb |= BACKEND_DISABLE(EVERGREEN_MAX_BACKENDS_MASK); + sp |= INACTIVE_SIMDS(EVERGREEN_MAX_SIMDS_MASK); } - } - /* enabled rb are just the one not disabled :) */ - disabled_rb_mask = tmp; - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); + WREG32(GRBM_GFX_INDEX, gfx); + WREG32(RLC_GFX_INDEX, gfx); - WREG32(GB_ADDR_CONFIG, gb_addr_config); - WREG32(DMIF_ADDR_CONFIG, gb_addr_config); - WREG32(HDP_ADDR_CONFIG, gb_addr_config); + WREG32(CC_RB_BACKEND_DISABLE, rb); + WREG32(CC_SYS_RB_BACKEND_DISABLE, rb); + WREG32(GC_USER_RB_BACKEND_DISABLE, rb); + WREG32(CC_GC_SHADER_PIPE_CONFIG, sp); + } - tmp = gb_addr_config & NUM_PIPES_MASK; - tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, - EVERGREEN_MAX_BACKENDS, disabled_rb_mask); - WREG32(GB_BACKEND_MAP, tmp); + grbm_gfx_index |= SE_BROADCAST_WRITES; + WREG32(GRBM_GFX_INDEX, grbm_gfx_index); + WREG32(RLC_GFX_INDEX, grbm_gfx_index); WREG32(CGTS_SYS_TCC_DISABLE, 0); WREG32(CGTS_TCC_DISABLE, 0); diff --git a/trunk/drivers/gpu/drm/radeon/evergreend.h b/trunk/drivers/gpu/drm/radeon/evergreend.h index 2773039b4902..79130bfd1d6f 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreend.h +++ b/trunk/drivers/gpu/drm/radeon/evergreend.h @@ -37,15 +37,6 @@ #define EVERGREEN_MAX_PIPES_MASK 0xFF #define EVERGREEN_MAX_LDS_NUM 0xFFFF -#define CYPRESS_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define BARTS_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define CAYMAN_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define JUNIPER_GB_ADDR_CONFIG_GOLDEN 0x02010002 -#define REDWOOD_GB_ADDR_CONFIG_GOLDEN 0x02010002 -#define TURKS_GB_ADDR_CONFIG_GOLDEN 0x02010002 -#define CEDAR_GB_ADDR_CONFIG_GOLDEN 0x02010001 -#define CAICOS_GB_ADDR_CONFIG_GOLDEN 0x02010001 - /* Registers */ #define RCU_IND_INDEX 0x100 @@ -63,7 +54,6 @@ #define BACKEND_DISABLE(x) ((x) << 16) #define GB_ADDR_CONFIG 0x98F8 #define NUM_PIPES(x) ((x) << 0) -#define NUM_PIPES_MASK 0x0000000f #define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) #define BANK_INTERLEAVE_SIZE(x) ((x) << 8) #define NUM_SHADER_ENGINES(x) ((x) << 12) @@ -462,7 +452,6 @@ #define MC_VM_MD_L1_TLB0_CNTL 0x2654 #define MC_VM_MD_L1_TLB1_CNTL 0x2658 #define MC_VM_MD_L1_TLB2_CNTL 0x265C -#define MC_VM_MD_L1_TLB3_CNTL 0x2698 #define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C #define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 diff --git a/trunk/drivers/gpu/drm/radeon/ni.c b/trunk/drivers/gpu/drm/radeon/ni.c index 3df4efa11942..ce4e7cc6c905 100644 --- a/trunk/drivers/gpu/drm/radeon/ni.c +++ b/trunk/drivers/gpu/drm/radeon/ni.c @@ -417,17 +417,215 @@ int ni_init_microcode(struct radeon_device *rdev) /* * Core functions */ +static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends_per_asic, + u32 *backend_disable_mask_per_asic, + u32 num_shader_engines) +{ + u32 backend_map = 0; + u32 enabled_backends_mask = 0; + u32 enabled_backends_count = 0; + u32 num_backends_per_se; + u32 cur_pipe; + u32 swizzle_pipe[CAYMAN_MAX_PIPES]; + u32 cur_backend = 0; + u32 i; + bool force_no_swizzle; + + /* force legal values */ + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_tile_pipes > rdev->config.cayman.max_tile_pipes) + num_tile_pipes = rdev->config.cayman.max_tile_pipes; + if (num_shader_engines < 1) + num_shader_engines = 1; + if (num_shader_engines > rdev->config.cayman.max_shader_engines) + num_shader_engines = rdev->config.cayman.max_shader_engines; + if (num_backends_per_asic < num_shader_engines) + num_backends_per_asic = num_shader_engines; + if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) + num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; + + /* make sure we have the same number of backends per se */ + num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); + /* set up the number of backends per se */ + num_backends_per_se = num_backends_per_asic / num_shader_engines; + if (num_backends_per_se > rdev->config.cayman.max_backends_per_se) { + num_backends_per_se = rdev->config.cayman.max_backends_per_se; + num_backends_per_asic = num_backends_per_se * num_shader_engines; + } + + /* create enable mask and count for enabled backends */ + for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { + if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends_per_asic) + break; + } + + /* force the backends mask to match the current number of backends */ + if (enabled_backends_count != num_backends_per_asic) { + u32 this_backend_enabled; + u32 shader_engine; + u32 backend_per_se; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + *backend_disable_mask_per_asic = CAYMAN_MAX_BACKENDS_MASK; + for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { + /* calc the current se */ + shader_engine = i / rdev->config.cayman.max_backends_per_se; + /* calc the backend per se */ + backend_per_se = i % rdev->config.cayman.max_backends_per_se; + /* default to not enabled */ + this_backend_enabled = 0; + if ((shader_engine < num_shader_engines) && + (backend_per_se < num_backends_per_se)) + this_backend_enabled = 1; + if (this_backend_enabled) { + enabled_backends_mask |= (1 << i); + *backend_disable_mask_per_asic &= ~(1 << i); + ++enabled_backends_count; + } + } + } + + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES); + switch (rdev->family) { + case CHIP_CAYMAN: + case CHIP_ARUBA: + force_no_swizzle = true; + break; + default: + force_no_swizzle = false; + break; + } + if (force_no_swizzle) { + bool last_backend_enabled = false; + + force_no_swizzle = false; + for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { + if (((enabled_backends_mask >> i) & 1) == 1) { + if (last_backend_enabled) + force_no_swizzle = true; + last_backend_enabled = true; + } else + last_backend_enabled = false; + } + } + + switch (num_tile_pipes) { + case 1: + case 3: + case 5: + case 7: + DRM_ERROR("odd number of pipes!\n"); + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + swizzle_pipe[3] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + } + break; + } + + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; + + backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); + + cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; + } + + return backend_map; +} + +static u32 cayman_get_disable_mask_per_asic(struct radeon_device *rdev, + u32 disable_mask_per_se, + u32 max_disable_mask_per_se, + u32 num_shader_engines) +{ + u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); + u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; + + if (num_shader_engines == 1) + return disable_mask_per_asic; + else if (num_shader_engines == 2) + return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); + else + return 0xffffffff; +} + static void cayman_gpu_init(struct radeon_device *rdev) { + u32 cc_rb_backend_disable = 0; + u32 cc_gc_shader_pipe_config; u32 gb_addr_config = 0; u32 mc_shared_chmap, mc_arb_ramcfg; + u32 gb_backend_map; u32 cgts_tcc_disable; u32 sx_debug_1; u32 smx_dc_ctl0; + u32 gc_user_shader_pipe_config; + u32 gc_user_rb_backend_disable; + u32 cgts_user_tcc_disable; u32 cgts_sm_ctrl_reg; u32 hdp_host_path_cntl; u32 tmp; - u32 disabled_rb_mask; int i, j; switch (rdev->family) { @@ -452,7 +650,6 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.sc_prim_fifo_size = 0x100; rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CAYMAN_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_ARUBA: default: @@ -490,7 +687,6 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.sc_prim_fifo_size = 0x40; rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = ARUBA_GB_ADDR_CONFIG_GOLDEN; break; } @@ -510,6 +706,39 @@ static void cayman_gpu_init(struct radeon_device *rdev) mc_shared_chmap = RREG32(MC_SHARED_CHMAP); mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); + cgts_tcc_disable = 0xffff0000; + for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++) + cgts_tcc_disable &= ~(1 << (16 + i)); + gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); + gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); + cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); + + rdev->config.cayman.num_shader_engines = rdev->config.cayman.max_shader_engines; + tmp = ((~gc_user_shader_pipe_config) & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; + rdev->config.cayman.num_shader_pipes_per_simd = r600_count_pipe_bits(tmp); + rdev->config.cayman.num_tile_pipes = rdev->config.cayman.max_tile_pipes; + tmp = ((~gc_user_shader_pipe_config) & INACTIVE_SIMDS_MASK) >> INACTIVE_SIMDS_SHIFT; + rdev->config.cayman.num_simds_per_se = r600_count_pipe_bits(tmp); + tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.cayman.num_backends_per_se = r600_count_pipe_bits(tmp); + tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.cayman.backend_disable_mask_per_asic = + cayman_get_disable_mask_per_asic(rdev, tmp, CAYMAN_MAX_BACKENDS_PER_SE_MASK, + rdev->config.cayman.num_shader_engines); + rdev->config.cayman.backend_map = + cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, + rdev->config.cayman.num_backends_per_se * + rdev->config.cayman.num_shader_engines, + &rdev->config.cayman.backend_disable_mask_per_asic, + rdev->config.cayman.num_shader_engines); + tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; + rdev->config.cayman.num_texture_channel_caches = r600_count_pipe_bits(tmp); + tmp = (mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT; + rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; + if (rdev->config.cayman.mem_max_burst_length_bytes > 512) + rdev->config.cayman.mem_max_burst_length_bytes = 512; tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; if (rdev->config.cayman.mem_row_size_in_kb > 4) @@ -519,6 +748,73 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.num_gpus = 1; rdev->config.cayman.multi_gpu_tile_size = 64; + //gb_addr_config = 0x02011003 +#if 0 + gb_addr_config = RREG32(GB_ADDR_CONFIG); +#else + gb_addr_config = 0; + switch (rdev->config.cayman.num_tile_pipes) { + case 1: + default: + gb_addr_config |= NUM_PIPES(0); + break; + case 2: + gb_addr_config |= NUM_PIPES(1); + break; + case 4: + gb_addr_config |= NUM_PIPES(2); + break; + case 8: + gb_addr_config |= NUM_PIPES(3); + break; + } + + tmp = (rdev->config.cayman.mem_max_burst_length_bytes / 256) - 1; + gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); + gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.cayman.num_shader_engines - 1); + tmp = (rdev->config.cayman.shader_engine_tile_size / 16) - 1; + gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); + switch (rdev->config.cayman.num_gpus) { + case 1: + default: + gb_addr_config |= NUM_GPUS(0); + break; + case 2: + gb_addr_config |= NUM_GPUS(1); + break; + case 4: + gb_addr_config |= NUM_GPUS(2); + break; + } + switch (rdev->config.cayman.multi_gpu_tile_size) { + case 16: + gb_addr_config |= MULTI_GPU_TILE_SIZE(0); + break; + case 32: + default: + gb_addr_config |= MULTI_GPU_TILE_SIZE(1); + break; + case 64: + gb_addr_config |= MULTI_GPU_TILE_SIZE(2); + break; + case 128: + gb_addr_config |= MULTI_GPU_TILE_SIZE(3); + break; + } + switch (rdev->config.cayman.mem_row_size_in_kb) { + case 1: + default: + gb_addr_config |= ROW_SIZE(0); + break; + case 2: + gb_addr_config |= ROW_SIZE(1); + break; + case 4: + gb_addr_config |= ROW_SIZE(2); + break; + } +#endif + tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; rdev->config.cayman.num_tile_pipes = (1 << tmp); tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; @@ -532,7 +828,17 @@ static void cayman_gpu_init(struct radeon_device *rdev) tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; rdev->config.cayman.mem_row_size_in_kb = 1 << tmp; - + //gb_backend_map = 0x76541032; +#if 0 + gb_backend_map = RREG32(GB_BACKEND_MAP); +#else + gb_backend_map = + cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, + rdev->config.cayman.num_backends_per_se * + rdev->config.cayman.num_shader_engines, + &rdev->config.cayman.backend_disable_mask_per_asic, + rdev->config.cayman.num_shader_engines); +#endif /* setup tiling info dword. gb_addr_config is not adequate since it does * not have bank info, so create a custom tiling dword. * bits 3:0 num_pipes @@ -560,49 +866,33 @@ static void cayman_gpu_init(struct radeon_device *rdev) /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ if (rdev->flags & RADEON_IS_IGP) rdev->config.cayman.tile_config |= 1 << 4; - else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.cayman.tile_config |= 1 << 4; - else - rdev->config.cayman.tile_config |= 0 << 4; - } + else + rdev->config.cayman.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; rdev->config.cayman.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.cayman.tile_config |= ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; - tmp = 0; - for (i = (rdev->config.cayman.max_shader_engines - 1); i >= 0; i--) { - u32 rb_disable_bitmap; - - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; - tmp <<= 4; - tmp |= rb_disable_bitmap; - } - /* enabled rb are just the one not disabled :) */ - disabled_rb_mask = tmp; - - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); - + rdev->config.cayman.backend_map = gb_backend_map; + WREG32(GB_BACKEND_MAP, gb_backend_map); WREG32(GB_ADDR_CONFIG, gb_addr_config); WREG32(DMIF_ADDR_CONFIG, gb_addr_config); WREG32(HDP_ADDR_CONFIG, gb_addr_config); - tmp = gb_addr_config & NUM_PIPES_MASK; - tmp = r6xx_remap_render_backend(rdev, tmp, - rdev->config.cayman.max_backends_per_se * - rdev->config.cayman.max_shader_engines, - CAYMAN_MAX_BACKENDS, disabled_rb_mask); - WREG32(GB_BACKEND_MAP, tmp); + /* primary versions */ + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); - cgts_tcc_disable = 0xffff0000; - for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++) - cgts_tcc_disable &= ~(1 << (16 + i)); WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable); + + /* user versions */ + WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable); WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); diff --git a/trunk/drivers/gpu/drm/radeon/nid.h b/trunk/drivers/gpu/drm/radeon/nid.h index a0b98066e207..2aa7046ada56 100644 --- a/trunk/drivers/gpu/drm/radeon/nid.h +++ b/trunk/drivers/gpu/drm/radeon/nid.h @@ -41,9 +41,6 @@ #define CAYMAN_MAX_TCC 16 #define CAYMAN_MAX_TCC_MASK 0xFF -#define CAYMAN_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define ARUBA_GB_ADDR_CONFIG_GOLDEN 0x12010001 - #define DMIF_ADDR_CONFIG 0xBD4 #define SRBM_GFX_CNTL 0x0E44 #define RINGID(x) (((x) & 0x3) << 0) @@ -151,8 +148,6 @@ #define CGTS_SYS_TCC_DISABLE 0x3F90 #define CGTS_USER_SYS_TCC_DISABLE 0x3F94 -#define RLC_GFX_INDEX 0x3FC4 - #define CONFIG_MEMSIZE 0x5428 #define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 @@ -217,12 +212,6 @@ #define SOFT_RESET_VGT (1 << 14) #define SOFT_RESET_IA (1 << 15) -#define GRBM_GFX_INDEX 0x802C -#define INSTANCE_INDEX(x) ((x) << 0) -#define SE_INDEX(x) ((x) << 16) -#define INSTANCE_BROADCAST_WRITES (1 << 30) -#define SE_BROADCAST_WRITES (1 << 31) - #define SCRATCH_REG0 0x8500 #define SCRATCH_REG1 0x8504 #define SCRATCH_REG2 0x8508 diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index 45cfcea63507..f388a1d73b63 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -1376,51 +1376,113 @@ int r600_asic_reset(struct radeon_device *rdev) return r600_gpu_soft_reset(rdev); } -u32 r6xx_remap_render_backend(struct radeon_device *rdev, - u32 tiling_pipe_num, - u32 max_rb_num, - u32 total_max_rb_num, - u32 disabled_rb_mask) -{ - u32 rendering_pipe_num, rb_num_width, req_rb_num; - u32 pipe_rb_ratio, pipe_rb_remain; - u32 data = 0, mask = 1 << (max_rb_num - 1); - unsigned i, j; - - /* mask out the RBs that don't exist on that asic */ - disabled_rb_mask |= (0xff << max_rb_num) & 0xff; - - rendering_pipe_num = 1 << tiling_pipe_num; - req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); - BUG_ON(rendering_pipe_num < req_rb_num); - - pipe_rb_ratio = rendering_pipe_num / req_rb_num; - pipe_rb_remain = rendering_pipe_num - pipe_rb_ratio * req_rb_num; - - if (rdev->family <= CHIP_RV740) { - /* r6xx/r7xx */ - rb_num_width = 2; - } else { - /* eg+ */ - rb_num_width = 4; - } +static u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask; + u32 enabled_backends_count; + u32 cur_pipe; + u32 swizzle_pipe[R6XX_MAX_PIPES]; + u32 cur_backend; + u32 i; - for (i = 0; i < max_rb_num; i++) { - if (!(mask & disabled_rb_mask)) { - for (j = 0; j < pipe_rb_ratio; j++) { - data <<= rb_num_width; - data |= max_rb_num - i - 1; - } - if (pipe_rb_remain) { - data <<= rb_num_width; - data |= max_rb_num - i - 1; - pipe_rb_remain--; - } + if (num_tile_pipes > R6XX_MAX_PIPES) + num_tile_pipes = R6XX_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > R6XX_MAX_BACKENDS) + num_backends = R6XX_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + for (i = 0; i < R6XX_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; } - mask >>= 1; + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R6XX_MAX_PIPES); + switch (num_tile_pipes) { + case 1: + swizzle_pipe[0] = 0; + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 3: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + break; + case 4: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + break; + case 5: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + break; + case 6: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 5; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + break; + case 7: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + break; + case 8: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + break; } - return data; + cur_backend = 0; + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; + + backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); + + cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; + } + + return backend_map; } int r600_count_pipe_bits(uint32_t val) @@ -1438,6 +1500,7 @@ void r600_gpu_init(struct radeon_device *rdev) { u32 tiling_config; u32 ramcfg; + u32 backend_map; u32 cc_rb_backend_disable; u32 cc_gc_shader_pipe_config; u32 tmp; @@ -1448,9 +1511,8 @@ void r600_gpu_init(struct radeon_device *rdev) u32 sq_thread_resource_mgmt = 0; u32 sq_stack_resource_mgmt_1 = 0; u32 sq_stack_resource_mgmt_2 = 0; - u32 disabled_rb_mask; - rdev->config.r600.tiling_group_size = 256; + /* FIXME: implement */ switch (rdev->family) { case CHIP_R600: rdev->config.r600.max_pipes = 4; @@ -1554,7 +1616,10 @@ void r600_gpu_init(struct radeon_device *rdev) rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); - + if ((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) + rdev->config.r600.tiling_group_size = 512; + else + rdev->config.r600.tiling_group_size = 256; tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT; if (tmp > 3) { tiling_config |= ROW_TILING(3); @@ -1566,36 +1631,32 @@ void r600_gpu_init(struct radeon_device *rdev) tiling_config |= BANK_SWAPS(1); cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; - tmp = R6XX_MAX_BACKENDS - - r600_count_pipe_bits((cc_rb_backend_disable >> 16) & R6XX_MAX_BACKENDS_MASK); - if (tmp < rdev->config.r600.max_backends) { - rdev->config.r600.max_backends = tmp; - } - - cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0x00ffff00; - tmp = R6XX_MAX_PIPES - - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R6XX_MAX_PIPES_MASK); - if (tmp < rdev->config.r600.max_pipes) { - rdev->config.r600.max_pipes = tmp; - } - tmp = R6XX_MAX_SIMDS - - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK); - if (tmp < rdev->config.r600.max_simds) { - rdev->config.r600.max_simds = tmp; - } - - disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK; - tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; - tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.r600.max_backends, - R6XX_MAX_BACKENDS, disabled_rb_mask); - tiling_config |= tmp << 16; - rdev->config.r600.backend_map = tmp; - + cc_rb_backend_disable |= + BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << rdev->config.r600.max_backends) & R6XX_MAX_BACKENDS_MASK); + + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; + cc_gc_shader_pipe_config |= + INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << rdev->config.r600.max_pipes) & R6XX_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << rdev->config.r600.max_simds) & R6XX_MAX_SIMDS_MASK); + + backend_map = r600_get_tile_pipe_to_backend_map(rdev->config.r600.max_tile_pipes, + (R6XX_MAX_BACKENDS - + r600_count_pipe_bits((cc_rb_backend_disable & + R6XX_MAX_BACKENDS_MASK) >> 16)), + (cc_rb_backend_disable >> 16)); rdev->config.r600.tile_config = tiling_config; + rdev->config.r600.backend_map = backend_map; + tiling_config |= BACKEND_MAP(backend_map); WREG32(GB_TILING_CONFIG, tiling_config); WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff); WREG32(HDP_TILING_CONFIG, tiling_config & 0xffff); + /* Setup pipes */ + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK); WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((tmp * 4) - 2) & VTX_REUSE_DEPTH_MASK); diff --git a/trunk/drivers/gpu/drm/radeon/r600d.h b/trunk/drivers/gpu/drm/radeon/r600d.h index a0dbf1fe6a40..15bd3b216243 100644 --- a/trunk/drivers/gpu/drm/radeon/r600d.h +++ b/trunk/drivers/gpu/drm/radeon/r600d.h @@ -219,8 +219,6 @@ #define BACKEND_MAP(x) ((x) << 16) #define GB_TILING_CONFIG 0x98F0 -#define PIPE_TILING__SHIFT 1 -#define PIPE_TILING__MASK 0x0000000e #define GC_USER_SHADER_PIPE_CONFIG 0x8954 #define INACTIVE_QD_PIPES(x) ((x) << 8) diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index 85dac33e3cce..2e24022b389a 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -1848,11 +1848,6 @@ extern struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock); extern void r600_hdmi_enable(struct drm_encoder *encoder); extern void r600_hdmi_disable(struct drm_encoder *encoder); extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); -extern u32 r6xx_remap_render_backend(struct radeon_device *rdev, - u32 tiling_pipe_num, - u32 max_rb_num, - u32 total_max_rb_num, - u32 enabled_rb_mask); /* * evergreen functions used by radeon_encoder.c diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cs.c b/trunk/drivers/gpu/drm/radeon/radeon_cs.c index 142f89462aa4..0137689ed461 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cs.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cs.c @@ -147,7 +147,6 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) sync_to_ring, p->ring); } -/* XXX: note that this is called from the legacy UMS CS ioctl as well */ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) { struct drm_radeon_cs *cs = data; @@ -246,25 +245,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) } } - /* these are KMS only */ - if (p->rdev) { - if ((p->cs_flags & RADEON_CS_USE_VM) && - !p->rdev->vm_manager.enabled) { - DRM_ERROR("VM not active on asic!\n"); - return -EINVAL; - } - - /* we only support VM on SI+ */ - if ((p->rdev->family >= CHIP_TAHITI) && - ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { - DRM_ERROR("VM required on SI+!\n"); - return -EINVAL; - } + if ((p->cs_flags & RADEON_CS_USE_VM) && + !p->rdev->vm_manager.enabled) { + DRM_ERROR("VM not active on asic!\n"); + return -EINVAL; + } - if (radeon_cs_get_ring(p, ring, priority)) - return -EINVAL; + /* we only support VM on SI+ */ + if ((p->rdev->family >= CHIP_TAHITI) && + ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { + DRM_ERROR("VM required on SI+!\n"); + return -EINVAL; } + if (radeon_cs_get_ring(p, ring, priority)) + return -EINVAL; + + /* deal with non-vm */ if ((p->chunk_ib_idx != -1) && ((p->cs_flags & RADEON_CS_USE_VM) == 0) && diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index 04ddc365a908..c2f473bc13b8 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -151,8 +151,6 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); - if (rdev->family == CHIP_RV740) - WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); @@ -365,6 +363,180 @@ void r700_cp_fini(struct radeon_device *rdev) /* * Core functions */ +static u32 r700_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask; + u32 enabled_backends_count; + u32 cur_pipe; + u32 swizzle_pipe[R7XX_MAX_PIPES]; + u32 cur_backend; + u32 i; + bool force_no_swizzle; + + if (num_tile_pipes > R7XX_MAX_PIPES) + num_tile_pipes = R7XX_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > R7XX_MAX_BACKENDS) + num_backends = R7XX_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + for (i = 0; i < R7XX_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + switch (rdev->family) { + case CHIP_RV770: + case CHIP_RV730: + force_no_swizzle = false; + break; + case CHIP_RV710: + case CHIP_RV740: + default: + force_no_swizzle = true; + break; + } + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES); + switch (num_tile_pipes) { + case 1: + swizzle_pipe[0] = 0; + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 3: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + } + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 3; + swizzle_pipe[3] = 1; + } + break; + case 5: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 5; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + } + break; + case 7: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + swizzle_pipe[6] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + swizzle_pipe[6] = 7; + swizzle_pipe[7] = 5; + } + break; + } + + cur_backend = 0; + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; + + backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); + + cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; + } + + return backend_map; +} + static void rv770_gpu_init(struct radeon_device *rdev) { int i, j, num_qd_pipes; @@ -380,17 +552,14 @@ static void rv770_gpu_init(struct radeon_device *rdev) u32 sq_thread_resource_mgmt; u32 hdp_host_path_cntl; u32 sq_dyn_gpr_size_simd_ab_0; + u32 backend_map; u32 gb_tiling_config = 0; u32 cc_rb_backend_disable = 0; u32 cc_gc_shader_pipe_config = 0; u32 mc_arb_ramcfg; - u32 db_debug4, tmp; - u32 inactive_pipes, shader_pipe_config; - u32 disabled_rb_mask; - unsigned active_number; + u32 db_debug4; /* setup chip specs */ - rdev->config.rv770.tiling_group_size = 256; switch (rdev->family) { case CHIP_RV770: rdev->config.rv770.max_pipes = 4; @@ -501,70 +670,33 @@ static void rv770_gpu_init(struct radeon_device *rdev) /* setup tiling, simd, pipe config */ mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); - shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); - inactive_pipes = (shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; - for (i = 0, tmp = 1, active_number = 0; i < R7XX_MAX_PIPES; i++) { - if (!(inactive_pipes & tmp)) { - active_number++; - } - tmp <<= 1; - } - if (active_number == 1) { - WREG32(SPI_CONFIG_CNTL, DISABLE_INTERP_1); - } else { - WREG32(SPI_CONFIG_CNTL, 0); - } - - cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; - tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16); - if (tmp < rdev->config.rv770.max_backends) { - rdev->config.rv770.max_backends = tmp; - } - - cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; - tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK); - if (tmp < rdev->config.rv770.max_pipes) { - rdev->config.rv770.max_pipes = tmp; - } - tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK); - if (tmp < rdev->config.rv770.max_simds) { - rdev->config.rv770.max_simds = tmp; - } - switch (rdev->config.rv770.max_tile_pipes) { case 1: default: - gb_tiling_config = PIPE_TILING(0); + gb_tiling_config |= PIPE_TILING(0); break; case 2: - gb_tiling_config = PIPE_TILING(1); + gb_tiling_config |= PIPE_TILING(1); break; case 4: - gb_tiling_config = PIPE_TILING(2); + gb_tiling_config |= PIPE_TILING(2); break; case 8: - gb_tiling_config = PIPE_TILING(3); + gb_tiling_config |= PIPE_TILING(3); break; } rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes; - disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK; - tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; - tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends, - R7XX_MAX_BACKENDS, disabled_rb_mask); - gb_tiling_config |= tmp << 16; - rdev->config.rv770.backend_map = tmp; - if (rdev->family == CHIP_RV770) gb_tiling_config |= BANK_TILING(1); - else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - gb_tiling_config |= BANK_TILING(1); - else - gb_tiling_config |= BANK_TILING(0); - } + else + gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3); gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + if ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) + rdev->config.rv770.tiling_group_size = 512; + else + rdev->config.rv770.tiling_group_size = 256; if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) { gb_tiling_config |= ROW_TILING(3); gb_tiling_config |= SAMPLE_SPLIT(3); @@ -576,19 +708,47 @@ static void rv770_gpu_init(struct radeon_device *rdev) } gb_tiling_config |= BANK_SWAPS(1); + + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; + cc_rb_backend_disable |= + BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK); + + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; + cc_gc_shader_pipe_config |= + INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << rdev->config.rv770.max_pipes) & R7XX_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << rdev->config.rv770.max_simds) & R7XX_MAX_SIMDS_MASK); + + if (rdev->family == CHIP_RV740) + backend_map = 0x28; + else + backend_map = r700_get_tile_pipe_to_backend_map(rdev, + rdev->config.rv770.max_tile_pipes, + (R7XX_MAX_BACKENDS - + r600_count_pipe_bits((cc_rb_backend_disable & + R7XX_MAX_BACKENDS_MASK) >> 16)), + (cc_rb_backend_disable >> 16)); + rdev->config.rv770.tile_config = gb_tiling_config; + rdev->config.rv770.backend_map = backend_map; + gb_tiling_config |= BACKEND_MAP(backend_map); WREG32(GB_TILING_CONFIG, gb_tiling_config); WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CGTS_SYS_TCC_DISABLE, 0); WREG32(CGTS_TCC_DISABLE, 0); WREG32(CGTS_USER_SYS_TCC_DISABLE, 0); WREG32(CGTS_USER_TCC_DISABLE, 0); - - num_qd_pipes = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); + num_qd_pipes = + R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK); WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK); @@ -649,6 +809,8 @@ static void rv770_gpu_init(struct radeon_device *rdev) WREG32(VGT_NUM_INSTANCES, 1); + WREG32(SPI_CONFIG_CNTL, GPR_WRITE_PRIORITY(0)); + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); WREG32(CP_PERFMON_CNTL, 0); diff --git a/trunk/drivers/gpu/drm/radeon/rv770d.h b/trunk/drivers/gpu/drm/radeon/rv770d.h index fdc089896011..9c549f702f2f 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770d.h +++ b/trunk/drivers/gpu/drm/radeon/rv770d.h @@ -106,13 +106,10 @@ #define BACKEND_MAP(x) ((x) << 16) #define GB_TILING_CONFIG 0x98F0 -#define PIPE_TILING__SHIFT 1 -#define PIPE_TILING__MASK 0x0000000e #define GC_USER_SHADER_PIPE_CONFIG 0x8954 #define INACTIVE_QD_PIPES(x) ((x) << 8) #define INACTIVE_QD_PIPES_MASK 0x0000FF00 -#define INACTIVE_QD_PIPES_SHIFT 8 #define INACTIVE_SIMDS(x) ((x) << 16) #define INACTIVE_SIMDS_MASK 0x00FF0000 @@ -177,7 +174,6 @@ #define MC_VM_MD_L1_TLB0_CNTL 0x2654 #define MC_VM_MD_L1_TLB1_CNTL 0x2658 #define MC_VM_MD_L1_TLB2_CNTL 0x265C -#define MC_VM_MD_L1_TLB3_CNTL 0x2698 #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 diff --git a/trunk/drivers/gpu/drm/ttm/ttm_bo.c b/trunk/drivers/gpu/drm/ttm/ttm_bo.c index b67cfcaa661f..36792bd4da77 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_bo.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_bo.c @@ -1834,7 +1834,6 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) spin_unlock(&glob->lru_lock); (void) ttm_bo_cleanup_refs(bo, false, false, false); kref_put(&bo->list_kref, ttm_bo_release_list); - spin_lock(&glob->lru_lock); continue; } diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index 21ee78226560..51c9ba5cd2fb 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c @@ -66,7 +66,7 @@ static int vmw_gmr2_bind(struct vmw_private *dev_priv, cmd += sizeof(remap_cmd) / sizeof(uint32); for (i = 0; i < num_pages; ++i) { - if (VMW_PPN_SIZE <= 4) + if (VMW_PPN_SIZE > 4) *cmd = page_to_pfn(*pages++); else *((uint64_t *)cmd) = page_to_pfn(*pages++); diff --git a/trunk/drivers/mfd/db8500-prcmu.c b/trunk/drivers/mfd/db8500-prcmu.c index 50e83dc5dc49..671c8bc14bbc 100644 --- a/trunk/drivers/mfd/db8500-prcmu.c +++ b/trunk/drivers/mfd/db8500-prcmu.c @@ -2735,7 +2735,6 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { REGULATOR_SUPPLY("vcore", "uart2"), REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"), - REGULATOR_SUPPLY("vddvario", "smsc911x.0"), }; static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { diff --git a/trunk/drivers/mtd/Kconfig b/trunk/drivers/mtd/Kconfig index 27143e042af5..5760c1a4b3f6 100644 --- a/trunk/drivers/mtd/Kconfig +++ b/trunk/drivers/mtd/Kconfig @@ -128,7 +128,7 @@ config MTD_AFS_PARTS config MTD_OF_PARTS tristate "OpenFirmware partitioning information support" - default y + default Y depends on OF help This provides a partition parsing function which derives diff --git a/trunk/drivers/mtd/bcm63xxpart.c b/trunk/drivers/mtd/bcm63xxpart.c index 63d2a64331f7..608321ee056e 100644 --- a/trunk/drivers/mtd/bcm63xxpart.c +++ b/trunk/drivers/mtd/bcm63xxpart.c @@ -4,7 +4,7 @@ * Copyright © 2006-2008 Florian Fainelli * Mike Albon * Copyright © 2009-2010 Daniel Dickinson - * Copyright © 2011-2012 Jonas Gorski + * Copyright © 2011 Jonas Gorski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -82,7 +82,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, int namelen = 0; int i; u32 computed_crc; - bool rootfs_first = false; if (bcm63xx_detect_cfe(master)) return -EINVAL; @@ -110,7 +109,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, char *boardid = &(buf->board_id[0]); char *tagversion = &(buf->tag_version[0]); - sscanf(buf->flash_image_start, "%u", &rootfsaddr); sscanf(buf->kernel_address, "%u", &kerneladdr); sscanf(buf->kernel_length, "%u", &kernellen); sscanf(buf->total_length, "%u", &totallen); @@ -119,19 +117,10 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, tagversion, boardid); kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; - rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE; + rootfsaddr = kerneladdr + kernellen; spareaddr = roundup(totallen, master->erasesize) + cfelen; sparelen = master->size - spareaddr - nvramlen; - - if (rootfsaddr < kerneladdr) { - /* default Broadcom layout */ - rootfslen = kerneladdr - rootfsaddr; - rootfs_first = true; - } else { - /* OpenWrt layout */ - rootfsaddr = kerneladdr + kernellen; - rootfslen = spareaddr - rootfsaddr; - } + rootfslen = spareaddr - rootfsaddr; } else { pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n", buf->header_crc, computed_crc); @@ -167,26 +156,18 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, curpart++; if (kernellen > 0) { - int kernelpart = curpart; - - if (rootfslen > 0 && rootfs_first) - kernelpart++; - parts[kernelpart].name = "kernel"; - parts[kernelpart].offset = kerneladdr; - parts[kernelpart].size = kernellen; + parts[curpart].name = "kernel"; + parts[curpart].offset = kerneladdr; + parts[curpart].size = kernellen; curpart++; } if (rootfslen > 0) { - int rootfspart = curpart; - - if (kernellen > 0 && rootfs_first) - rootfspart--; - parts[rootfspart].name = "rootfs"; - parts[rootfspart].offset = rootfsaddr; - parts[rootfspart].size = rootfslen; - if (sparelen > 0 && !rootfs_first) - parts[rootfspart].size += sparelen; + parts[curpart].name = "rootfs"; + parts[curpart].offset = rootfsaddr; + parts[curpart].size = rootfslen; + if (sparelen > 0) + parts[curpart].size += sparelen; curpart++; } diff --git a/trunk/drivers/mtd/chips/cfi_cmdset_0002.c b/trunk/drivers/mtd/chips/cfi_cmdset_0002.c index 22d0493a026f..d02592e6a0f0 100644 --- a/trunk/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/trunk/drivers/mtd/chips/cfi_cmdset_0002.c @@ -317,7 +317,7 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd) if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { cfi->cfiq->EraseRegionInfo[0] |= 0x0040; - pr_warning("%s: Bad S29GL064N CFI data; adjust from 64 to 128 sectors\n", mtd->name); + pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name); } } @@ -328,23 +328,10 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd) if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; - pr_warning("%s: Bad S29GL032N CFI data; adjust from 127 to 63 sectors\n", mtd->name); + pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name); } } -static void fixup_s29ns512p_sectors(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - - /* - * S29NS512P flash uses more than 8bits to report number of sectors, - * which is not permitted by CFI. - */ - cfi->cfiq->EraseRegionInfo[0] = 0x020001ff; - pr_warning("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n", mtd->name); -} - /* Used to fix CFI-Tables of chips without Extended Query Tables */ static struct cfi_fixup cfi_nopri_fixup_table[] = { { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ @@ -375,7 +362,6 @@ static struct cfi_fixup cfi_fixup_table[] = { { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, - { CFI_MFR_AMD, 0x3f00, fixup_s29ns512p_sectors }, { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ diff --git a/trunk/drivers/mtd/cmdlinepart.c b/trunk/drivers/mtd/cmdlinepart.c index 4558e0f4d07f..ddf9ec6d9168 100644 --- a/trunk/drivers/mtd/cmdlinepart.c +++ b/trunk/drivers/mtd/cmdlinepart.c @@ -70,7 +70,7 @@ struct cmdline_mtd_partition { /* mtdpart_setup() parses into here */ static struct cmdline_mtd_partition *partitions; -/* the command line passed to mtdpart_setup() */ +/* the command line passed to mtdpart_setupd() */ static char *cmdline; static int cmdline_parsed = 0; diff --git a/trunk/drivers/mtd/devices/block2mtd.c b/trunk/drivers/mtd/devices/block2mtd.c index 681e2ee0f2d6..a4a80b742e65 100644 --- a/trunk/drivers/mtd/devices/block2mtd.c +++ b/trunk/drivers/mtd/devices/block2mtd.c @@ -52,6 +52,8 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) while (pages) { page = page_read(mapping, index); + if (!page) + return -ENOMEM; if (IS_ERR(page)) return PTR_ERR(page); @@ -110,6 +112,8 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, len = len - cpylen; page = page_read(dev->blkdev->bd_inode->i_mapping, index); + if (!page) + return -ENOMEM; if (IS_ERR(page)) return PTR_ERR(page); @@ -144,6 +148,8 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, len = len - cpylen; page = page_read(mapping, index); + if (!page) + return -ENOMEM; if (IS_ERR(page)) return PTR_ERR(page); @@ -265,6 +271,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) dev->mtd.flags = MTD_CAP_RAM; dev->mtd._erase = block2mtd_erase; dev->mtd._write = block2mtd_write; + dev->mtd._writev = mtd_writev; dev->mtd._sync = block2mtd_sync; dev->mtd._read = block2mtd_read; dev->mtd.priv = dev; diff --git a/trunk/drivers/mtd/devices/docg3.c b/trunk/drivers/mtd/devices/docg3.c index f70854d728fe..50aa90aa7a7f 100644 --- a/trunk/drivers/mtd/devices/docg3.c +++ b/trunk/drivers/mtd/devices/docg3.c @@ -227,7 +227,7 @@ static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, u8 data8, *dst8; doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len); - cdr = len & 0x1; + cdr = len & 0x3; len4 = len - cdr; if (first) @@ -732,24 +732,12 @@ static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1, * @len: the number of bytes to be read (must be a multiple of 4) * @buf: the buffer to be filled in (or NULL is forget bytes) * @first: 1 if first time read, DOC_READADDRESS should be set - * @last_odd: 1 if last read ended up on an odd byte - * - * Reads bytes from a prepared page. There is a trickery here : if the last read - * ended up on an odd offset in the 1024 bytes double page, ie. between the 2 - * planes, the first byte must be read apart. If a word (16bit) read was used, - * the read would return the byte of plane 2 as low *and* high endian, which - * will mess the read. * */ static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, - int first, int last_odd) + int first) { - if (last_odd && len > 0) { - doc_read_data_area(docg3, buf, 1, first); - doc_read_data_area(docg3, buf ? buf + 1 : buf, len - 1, 0); - } else { - doc_read_data_area(docg3, buf, len, first); - } + doc_read_data_area(docg3, buf, len, first); doc_delay(docg3, 2); return len; } @@ -862,7 +850,6 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, u8 *buf = ops->datbuf; size_t len, ooblen, nbdata, nboob; u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1; - int max_bitflips = 0; if (buf) len = ops->len; @@ -889,7 +876,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, ret = 0; skip = from % DOC_LAYOUT_PAGE_SIZE; mutex_lock(&docg3->cascade->lock); - while (ret >= 0 && (len > 0 || ooblen > 0)) { + while (!ret && (len > 0 || ooblen > 0)) { calc_block_sector(from - skip, &block0, &block1, &page, &ofs, docg3->reliable); nbdata = min_t(size_t, len, DOC_LAYOUT_PAGE_SIZE - skip); @@ -900,20 +887,20 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); if (ret < 0) goto err_in_read; - ret = doc_read_page_getbytes(docg3, skip, NULL, 1, 0); + ret = doc_read_page_getbytes(docg3, skip, NULL, 1); if (ret < skip) goto err_in_read; - ret = doc_read_page_getbytes(docg3, nbdata, buf, 0, skip % 2); + ret = doc_read_page_getbytes(docg3, nbdata, buf, 0); if (ret < nbdata) goto err_in_read; doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE - nbdata - skip, - NULL, 0, (skip + nbdata) % 2); - ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0, 0); + NULL, 0); + ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0); if (ret < nboob) goto err_in_read; doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob, - NULL, 0, nboob % 2); + NULL, 0); doc_get_bch_hw_ecc(docg3, hwecc); eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); @@ -949,8 +936,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, } if (ret > 0) { mtd->ecc_stats.corrected += ret; - max_bitflips = max(max_bitflips, ret); - ret = max_bitflips; + ret = -EUCLEAN; } } @@ -1018,7 +1004,7 @@ static int doc_reload_bbt(struct docg3 *docg3) DOC_LAYOUT_PAGE_SIZE); if (!ret) doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE, - buf, 1, 0); + buf, 1); buf += DOC_LAYOUT_PAGE_SIZE; } doc_read_page_finish(docg3); @@ -1078,10 +1064,10 @@ static int doc_get_erase_count(struct docg3 *docg3, loff_t from) ret = doc_reset_seq(docg3); if (!ret) ret = doc_read_page_prepare(docg3, block0, block1, page, - ofs + DOC_LAYOUT_WEAR_OFFSET, 0); + ofs + DOC_LAYOUT_WEAR_OFFSET); if (!ret) ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE, - buf, 1, 0); + buf, 1); doc_read_page_finish(docg3); if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK)) diff --git a/trunk/drivers/mtd/devices/m25p80.c b/trunk/drivers/mtd/devices/m25p80.c index 5d0d68c3fe27..1924d247c1cb 100644 --- a/trunk/drivers/mtd/devices/m25p80.c +++ b/trunk/drivers/mtd/devices/m25p80.c @@ -639,16 +639,12 @@ static const struct spi_device_id m25p_ids[] = { { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, - /* Everspin */ - { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) }, - /* Intel/Numonyx -- xxxs33b */ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, /* Macronix */ - { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, @@ -732,7 +728,6 @@ static const struct spi_device_id m25p_ids[] = { { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, - { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, /* Catalyst / On Semiconductor -- non-JEDEC */ { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, diff --git a/trunk/drivers/mtd/devices/spear_smi.c b/trunk/drivers/mtd/devices/spear_smi.c index 67960362681e..797d43cd3550 100644 --- a/trunk/drivers/mtd/devices/spear_smi.c +++ b/trunk/drivers/mtd/devices/spear_smi.c @@ -990,9 +990,9 @@ static int __devinit spear_smi_probe(struct platform_device *pdev) goto err_clk; } - ret = clk_prepare_enable(dev->clk); + ret = clk_enable(dev->clk); if (ret) - goto err_clk_prepare_enable; + goto err_clk_enable; ret = request_irq(irq, spear_smi_int_handler, 0, pdev->name, dev); if (ret) { @@ -1020,8 +1020,8 @@ static int __devinit spear_smi_probe(struct platform_device *pdev) free_irq(irq, dev); platform_set_drvdata(pdev, NULL); err_irq: - clk_disable_unprepare(dev->clk); -err_clk_prepare_enable: + clk_disable(dev->clk); +err_clk_enable: clk_put(dev->clk); err_clk: iounmap(dev->io_base); @@ -1074,7 +1074,7 @@ static int __devexit spear_smi_remove(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); free_irq(irq, dev); - clk_disable_unprepare(dev->clk); + clk_disable(dev->clk); clk_put(dev->clk); iounmap(dev->io_base); kfree(dev); @@ -1091,7 +1091,7 @@ int spear_smi_suspend(struct platform_device *pdev, pm_message_t state) struct spear_smi *dev = platform_get_drvdata(pdev); if (dev && dev->clk) - clk_disable_unprepare(dev->clk); + clk_disable(dev->clk); return 0; } @@ -1102,7 +1102,7 @@ int spear_smi_resume(struct platform_device *pdev) int ret = -EPERM; if (dev && dev->clk) - ret = clk_prepare_enable(dev->clk); + ret = clk_enable(dev->clk); if (!ret) spear_smi_hw_init(dev); diff --git a/trunk/drivers/mtd/lpddr/qinfo_probe.c b/trunk/drivers/mtd/lpddr/qinfo_probe.c index 45abed67f1ef..dbfe17baf046 100644 --- a/trunk/drivers/mtd/lpddr/qinfo_probe.c +++ b/trunk/drivers/mtd/lpddr/qinfo_probe.c @@ -57,7 +57,7 @@ static struct qinfo_query_info qinfo_array[] = { static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str) { - int qinfo_lines = ARRAY_SIZE(qinfo_array); + int qinfo_lines = sizeof(qinfo_array)/sizeof(struct qinfo_query_info); int i; int bankwidth = map_bankwidth(map) * 8; int major, minor; diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig index 5ba2458e799a..8af67cfd671a 100644 --- a/trunk/drivers/mtd/maps/Kconfig +++ b/trunk/drivers/mtd/maps/Kconfig @@ -224,7 +224,7 @@ config MTD_CK804XROM config MTD_SCB2_FLASH tristate "BIOS flash chip on Intel SCB2 boards" - depends on X86 && MTD_JEDECPROBE && PCI + depends on X86 && MTD_JEDECPROBE help Support for treating the BIOS flash chip on Intel SCB2 boards as an MTD device - with this you can reprogram your BIOS. diff --git a/trunk/drivers/mtd/maps/intel_vr_nor.c b/trunk/drivers/mtd/maps/intel_vr_nor.c index 93f03175c82d..92e1f41634c7 100644 --- a/trunk/drivers/mtd/maps/intel_vr_nor.c +++ b/trunk/drivers/mtd/maps/intel_vr_nor.c @@ -260,7 +260,18 @@ static struct pci_driver vr_nor_pci_driver = { .id_table = vr_nor_pci_ids, }; -module_pci_driver(vr_nor_pci_driver); +static int __init vr_nor_mtd_init(void) +{ + return pci_register_driver(&vr_nor_pci_driver); +} + +static void __exit vr_nor_mtd_exit(void) +{ + pci_unregister_driver(&vr_nor_pci_driver); +} + +module_init(vr_nor_mtd_init); +module_exit(vr_nor_mtd_exit); MODULE_AUTHOR("Andy Lowe"); MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); diff --git a/trunk/drivers/mtd/maps/pci.c b/trunk/drivers/mtd/maps/pci.c index f14ce0af763f..1d005a3e9b41 100644 --- a/trunk/drivers/mtd/maps/pci.c +++ b/trunk/drivers/mtd/maps/pci.c @@ -352,7 +352,18 @@ static struct pci_driver mtd_pci_driver = { .id_table = mtd_pci_ids, }; -module_pci_driver(mtd_pci_driver); +static int __init mtd_pci_maps_init(void) +{ + return pci_register_driver(&mtd_pci_driver); +} + +static void __exit mtd_pci_maps_exit(void) +{ + pci_unregister_driver(&mtd_pci_driver); +} + +module_init(mtd_pci_maps_init); +module_exit(mtd_pci_maps_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Russell King "); diff --git a/trunk/drivers/mtd/maps/scb2_flash.c b/trunk/drivers/mtd/maps/scb2_flash.c index 9dcbc684abdb..934a72c80078 100644 --- a/trunk/drivers/mtd/maps/scb2_flash.c +++ b/trunk/drivers/mtd/maps/scb2_flash.c @@ -234,7 +234,20 @@ static struct pci_driver scb2_flash_driver = { .remove = __devexit_p(scb2_flash_remove), }; -module_pci_driver(scb2_flash_driver); +static int __init +scb2_flash_init(void) +{ + return pci_register_driver(&scb2_flash_driver); +} + +static void __exit +scb2_flash_exit(void) +{ + pci_unregister_driver(&scb2_flash_driver); +} + +module_init(scb2_flash_init); +module_exit(scb2_flash_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Hockin "); diff --git a/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c b/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c index e7534c82f93a..71b0ba797912 100644 --- a/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c @@ -59,7 +59,7 @@ static struct mtd_partition bigflash_parts[] = { } }; -static const char *part_probes[] __initconst = {"cmdlinepart", "RedBoot", NULL}; +static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL}; #define init_sbc82xx_one_flash(map, br, or) \ do { \ diff --git a/trunk/drivers/mtd/mtdcore.c b/trunk/drivers/mtd/mtdcore.c index 575730744fdb..c837507dfb1c 100644 --- a/trunk/drivers/mtd/mtdcore.c +++ b/trunk/drivers/mtd/mtdcore.c @@ -250,43 +250,6 @@ static ssize_t mtd_name_show(struct device *dev, } static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); -static ssize_t mtd_ecc_strength_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mtd_info *mtd = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength); -} -static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL); - -static ssize_t mtd_bitflip_threshold_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct mtd_info *mtd = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold); -} - -static ssize_t mtd_bitflip_threshold_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct mtd_info *mtd = dev_get_drvdata(dev); - unsigned int bitflip_threshold; - int retval; - - retval = kstrtouint(buf, 0, &bitflip_threshold); - if (retval) - return retval; - - mtd->bitflip_threshold = bitflip_threshold; - return count; -} -static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR, - mtd_bitflip_threshold_show, - mtd_bitflip_threshold_store); - static struct attribute *mtd_attrs[] = { &dev_attr_type.attr, &dev_attr_flags.attr, @@ -297,8 +260,6 @@ static struct attribute *mtd_attrs[] = { &dev_attr_oobsize.attr, &dev_attr_numeraseregions.attr, &dev_attr_name.attr, - &dev_attr_ecc_strength.attr, - &dev_attr_bitflip_threshold.attr, NULL, }; @@ -361,10 +322,6 @@ int add_mtd_device(struct mtd_info *mtd) mtd->index = i; mtd->usecount = 0; - /* default value if not set by driver */ - if (mtd->bitflip_threshold == 0) - mtd->bitflip_threshold = mtd->ecc_strength; - if (is_power_of_2(mtd->erasesize)) mtd->erasesize_shift = ffs(mtd->erasesize) - 1; else @@ -800,24 +757,12 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - int ret_code; *retlen = 0; if (from < 0 || from > mtd->size || len > mtd->size - from) return -EINVAL; if (!len) return 0; - - /* - * In the absence of an error, drivers return a non-negative integer - * representing the maximum number of bitflips that were corrected on - * any one ecc region (if applicable; zero otherwise). - */ - ret_code = mtd->_read(mtd, from, len, retlen, buf); - if (unlikely(ret_code < 0)) - return ret_code; - if (mtd->ecc_strength == 0) - return 0; /* device lacks ecc */ - return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; + return mtd->_read(mtd, from, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_read); diff --git a/trunk/drivers/mtd/mtdpart.c b/trunk/drivers/mtd/mtdpart.c index d518e4db8a0b..9651c06de0a9 100644 --- a/trunk/drivers/mtd/mtdpart.c +++ b/trunk/drivers/mtd/mtdpart.c @@ -67,12 +67,12 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, stats = part->master->ecc_stats; res = part->master->_read(part->master, from + part->offset, len, retlen, buf); - if (unlikely(mtd_is_eccerr(res))) - mtd->ecc_stats.failed += - part->master->ecc_stats.failed - stats.failed; - else - mtd->ecc_stats.corrected += - part->master->ecc_stats.corrected - stats.corrected; + if (unlikely(res)) { + if (mtd_is_bitflip(res)) + mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; + if (mtd_is_eccerr(res)) + mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; + } return res; } @@ -517,8 +517,6 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, slave->mtd.ecclayout = master->ecclayout; slave->mtd.ecc_strength = master->ecc_strength; - slave->mtd.bitflip_threshold = master->bitflip_threshold; - if (master->_block_isbad) { uint64_t offs = 0; diff --git a/trunk/drivers/mtd/nand/Kconfig b/trunk/drivers/mtd/nand/Kconfig index 31bb7e5b504a..7d17cecad69d 100644 --- a/trunk/drivers/mtd/nand/Kconfig +++ b/trunk/drivers/mtd/nand/Kconfig @@ -115,46 +115,6 @@ config MTD_NAND_OMAP2 Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4 platforms. -config MTD_NAND_OMAP_BCH - depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3 - bool "Enable support for hardware BCH error correction" - default n - select BCH - select BCH_CONST_PARAMS - help - Support for hardware BCH error correction. - -choice - prompt "BCH error correction capability" - depends on MTD_NAND_OMAP_BCH - -config MTD_NAND_OMAP_BCH8 - bool "8 bits / 512 bytes (recommended)" - help - Support correcting up to 8 bitflips per 512-byte block. - This will use 13 bytes of spare area per 512 bytes of page data. - This is the recommended mode, as 4-bit mode does not work - on some OMAP3 revisions, due to a hardware bug. - -config MTD_NAND_OMAP_BCH4 - bool "4 bits / 512 bytes" - help - Support correcting up to 4 bitflips per 512-byte block. - This will use 7 bytes of spare area per 512 bytes of page data. - Note that this mode does not work on some OMAP3 revisions, due to a - hardware bug. Please check your OMAP datasheet before selecting this - mode. - -endchoice - -if MTD_NAND_OMAP_BCH -config BCH_CONST_M - default 13 -config BCH_CONST_T - default 4 if MTD_NAND_OMAP_BCH4 - default 8 if MTD_NAND_OMAP_BCH8 -endif - config MTD_NAND_IDS tristate @@ -480,7 +440,7 @@ config MTD_NAND_NANDSIM config MTD_NAND_GPMI_NAND bool "GPMI NAND Flash Controller driver" - depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q) + depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28) help Enables NAND Flash support for IMX23 or IMX28. The GPMI controller is very powerful, with the help of BCH diff --git a/trunk/drivers/mtd/nand/alauda.c b/trunk/drivers/mtd/nand/alauda.c index 60a0dfdb0808..4f20e1d8bef1 100644 --- a/trunk/drivers/mtd/nand/alauda.c +++ b/trunk/drivers/mtd/nand/alauda.c @@ -414,7 +414,7 @@ static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len, } err = 0; if (corrected) - err = 1; /* return max_bitflips per ecc step */ + err = -EUCLEAN; if (uncorrected) err = -EBADMSG; out: @@ -446,7 +446,7 @@ static int alauda_read(struct mtd_info *mtd, loff_t from, size_t len, } err = 0; if (corrected) - err = 1; /* return max_bitflips per ecc step */ + err = -EUCLEAN; if (uncorrected) err = -EBADMSG; return err; diff --git a/trunk/drivers/mtd/nand/atmel_nand.c b/trunk/drivers/mtd/nand/atmel_nand.c index 97ac6712bb19..2165576a1c67 100644 --- a/trunk/drivers/mtd/nand/atmel_nand.c +++ b/trunk/drivers/mtd/nand/atmel_nand.c @@ -324,10 +324,9 @@ static int atmel_nand_calculate(struct mtd_info *mtd, * mtd: mtd info structure * chip: nand chip info structure * buf: buffer to store read data - * oob_required: caller expects OOB data read to chip->oob_poi */ -static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int atmel_nand_read_page(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -336,7 +335,6 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *oob = chip->oob_poi; uint8_t *ecc_pos; int stat; - unsigned int max_bitflips = 0; /* * Errata: ALE is incorrectly wired up to the ECC controller @@ -373,12 +371,10 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, /* check if there's an error */ stat = chip->ecc.correct(mtd, p, oob, NULL); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } /* get back to oob start (end of page) */ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); @@ -386,7 +382,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, /* read the oob */ chip->read_buf(mtd, oob, mtd->oobsize); - return max_bitflips; + return 0; } /* diff --git a/trunk/drivers/mtd/nand/au1550nd.c b/trunk/drivers/mtd/nand/au1550nd.c index 9f609d2dcf62..73abbc3e093e 100644 --- a/trunk/drivers/mtd/nand/au1550nd.c +++ b/trunk/drivers/mtd/nand/au1550nd.c @@ -508,6 +508,8 @@ static int __devinit au1550nd_probe(struct platform_device *pdev) this->chip_delay = 30; this->ecc.mode = NAND_ECC_SOFT; + this->options = NAND_NO_AUTOINCR; + if (pd->devwidth) this->options |= NAND_BUSWIDTH_16; diff --git a/trunk/drivers/mtd/nand/bcm_umi_bch.c b/trunk/drivers/mtd/nand/bcm_umi_bch.c index 5914bb32e001..a930666d0687 100644 --- a/trunk/drivers/mtd/nand/bcm_umi_bch.c +++ b/trunk/drivers/mtd/nand/bcm_umi_bch.c @@ -22,9 +22,9 @@ /* ---- Private Function Prototypes -------------------------------------- */ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, int page); + struct nand_chip *chip, uint8_t *buf, int page); static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required); + struct nand_chip *chip, const uint8_t *buf); /* ---- Private Variables ------------------------------------------------ */ @@ -103,12 +103,11 @@ static struct nand_ecclayout nand_hw_eccoob_4096 = { * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data -* @oob_required: caller expects OOB data read to chip->oob_poi * ***************************************************************************/ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, - int oob_required, int page) + int page) { int sectorIdx = 0; int eccsize = chip->ecc.size; @@ -117,7 +116,6 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, uint8_t eccCalc[NAND_ECC_NUM_BYTES]; int sectorOobSize = mtd->oobsize / eccsteps; int stat; - unsigned int max_bitflips = 0; for (sectorIdx = 0; sectorIdx < eccsteps; sectorIdx++, datap += eccsize) { @@ -179,10 +177,9 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, } #endif mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); } } - return max_bitflips; + return 0; } /**************************************************************************** @@ -191,11 +188,10 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer -* @oob_required: must write chip->oob_poi to OOB * ***************************************************************************/ static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { int sectorIdx = 0; int eccsize = chip->ecc.size; diff --git a/trunk/drivers/mtd/nand/bcm_umi_nand.c b/trunk/drivers/mtd/nand/bcm_umi_nand.c index c855e7cd337b..6908cdde3065 100644 --- a/trunk/drivers/mtd/nand/bcm_umi_nand.c +++ b/trunk/drivers/mtd/nand/bcm_umi_nand.c @@ -341,7 +341,7 @@ static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf, * for MLC parts which may have permanently stuck bits. */ struct nand_chip *chip = mtd->priv; - int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0, 0); + int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0); if (ret < 0) return -EFAULT; else { @@ -476,7 +476,12 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) this->badblock_pattern = &largepage_bbt; } - this->ecc.strength = 8; + /* + * FIXME: ecc strength value of 6 bits per 512 bytes of data is a + * conservative guess, given 13 ecc bytes and using bch alg. + * (Assume Galois field order m=15 to allow a margin of error.) + */ + this->ecc.strength = 6; #endif diff --git a/trunk/drivers/mtd/nand/bf5xx_nand.c b/trunk/drivers/mtd/nand/bf5xx_nand.c index 3f1c18599cbd..d7b86b925de5 100644 --- a/trunk/drivers/mtd/nand/bf5xx_nand.c +++ b/trunk/drivers/mtd/nand/bf5xx_nand.c @@ -558,7 +558,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, } static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { bf5xx_nand_read_buf(mtd, buf, mtd->writesize); bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -567,7 +567,7 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip } static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { bf5xx_nand_write_buf(mtd, buf, mtd->writesize); bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); diff --git a/trunk/drivers/mtd/nand/cafe_nand.c b/trunk/drivers/mtd/nand/cafe_nand.c index 41371ba1a811..2a96e1a12062 100644 --- a/trunk/drivers/mtd/nand/cafe_nand.c +++ b/trunk/drivers/mtd/nand/cafe_nand.c @@ -364,27 +364,25 @@ static int cafe_nand_write_oob(struct mtd_info *mtd, /* Don't use -- use nand_read_oob_std for now */ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - return 0; + return 1; } /** * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller expects OOB data read to chip->oob_poi * * The hw generator calculates the error syndrome automatically. Therefor * we need a special oob layout and handling. */ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct cafe_priv *cafe = mtd->priv; - unsigned int max_bitflips = 0; cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", cafe_readl(cafe, NAND_ECC_RESULT), @@ -451,11 +449,10 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, } else { dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n); mtd->ecc_stats.corrected += n; - max_bitflips = max_t(unsigned int, max_bitflips, n); } } - return max_bitflips; + return 0; } static struct nand_ecclayout cafe_oobinfo_2048 = { @@ -521,8 +518,7 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { struct cafe_priv *cafe = mtd->priv; @@ -534,17 +530,16 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, } static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page, - int cached, int raw) + const uint8_t *buf, int page, int cached, int raw) { int status; chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (unlikely(raw)) - chip->ecc.write_page_raw(mtd, chip, buf, oob_required); + chip->ecc.write_page_raw(mtd, chip, buf); else - chip->ecc.write_page(mtd, chip, buf, oob_required); + chip->ecc.write_page(mtd, chip, buf); /* * Cached progamming disabled for now, Not sure if its worth the @@ -690,7 +685,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, /* Enable the following for a flash based bad block table */ cafe->nand.bbt_options = NAND_BBT_USE_FLASH; - cafe->nand.options = NAND_OWN_BUFFERS; + cafe->nand.options = NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; if (skipbbt) { cafe->nand.options |= NAND_SKIP_BBTSCAN; @@ -893,7 +888,17 @@ static struct pci_driver cafe_nand_pci_driver = { .resume = cafe_nand_resume, }; -module_pci_driver(cafe_nand_pci_driver); +static int __init cafe_nand_init(void) +{ + return pci_register_driver(&cafe_nand_pci_driver); +} + +static void __exit cafe_nand_exit(void) +{ + pci_unregister_driver(&cafe_nand_pci_driver); +} +module_init(cafe_nand_init); +module_exit(cafe_nand_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); diff --git a/trunk/drivers/mtd/nand/cs553x_nand.c b/trunk/drivers/mtd/nand/cs553x_nand.c index adb6c3ef37fb..821c34c62500 100644 --- a/trunk/drivers/mtd/nand/cs553x_nand.c +++ b/trunk/drivers/mtd/nand/cs553x_nand.c @@ -240,6 +240,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) /* Enable the following for a flash based bad block table */ this->bbt_options = NAND_BBT_USE_FLASH; + this->options = NAND_NO_AUTOINCR; /* Scan to find existence of the device */ if (nand_scan(new_mtd, 1)) { diff --git a/trunk/drivers/mtd/nand/denali.c b/trunk/drivers/mtd/nand/denali.c index 0650aafa0dd2..a9e57d686297 100644 --- a/trunk/drivers/mtd/nand/denali.c +++ b/trunk/drivers/mtd/nand/denali.c @@ -924,10 +924,9 @@ bool is_erased(uint8_t *buf, int len) #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, - uint32_t irq_status, unsigned int *max_bitflips) + uint32_t irq_status) { bool check_erased_page = false; - unsigned int bitflips = 0; if (irq_status & INTR_STATUS__ECC_ERR) { /* read the ECC errors. we'll ignore them for now */ @@ -966,7 +965,6 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, /* correct the ECC error */ buf[offset] ^= err_correction_value; denali->mtd.ecc_stats.corrected++; - bitflips++; } } else { /* if the error is not correctable, need to @@ -986,7 +984,6 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, clear_interrupts(denali); denali_set_intr_modes(denali, true); } - *max_bitflips = bitflips; return check_erased_page; } @@ -1087,7 +1084,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, * by write_page above. * */ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { /* for regular page writes, we let HW handle all the ECC * data written to the device. */ @@ -1099,7 +1096,7 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, * write_page() function above. */ static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { /* for raw page writes, we want to disable ECC and simply write whatever data is in the buffer. */ @@ -1113,17 +1110,17 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, } static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { read_oob_data(mtd, chip->oob_poi, page); - return 0; + return 0; /* notify NAND core to send command to + NAND device. */ } static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { - unsigned int max_bitflips; struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; @@ -1156,7 +1153,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, memcpy(buf, denali->buf.buf, mtd->writesize); - check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips); + check_erased_page = handle_ecc(denali, buf, irq_status); denali_enable_dma(denali, false); if (check_erased_page) { @@ -1170,11 +1167,11 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, denali->mtd.ecc_stats.failed++; } } - return max_bitflips; + return 0; } static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); @@ -1705,4 +1702,17 @@ static struct pci_driver denali_pci_driver = { .remove = denali_pci_remove, }; -module_pci_driver(denali_pci_driver); +static int __devinit denali_init(void) +{ + printk(KERN_INFO "Spectra MTD driver\n"); + return pci_register_driver(&denali_pci_driver); +} + +/* Free memory */ +static void __devexit denali_exit(void) +{ + pci_unregister_driver(&denali_pci_driver); +} + +module_init(denali_init); +module_exit(denali_exit); diff --git a/trunk/drivers/mtd/nand/docg4.c b/trunk/drivers/mtd/nand/docg4.c index a225e49a5623..b08202664543 100644 --- a/trunk/drivers/mtd/nand/docg4.c +++ b/trunk/drivers/mtd/nand/docg4.c @@ -720,7 +720,6 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; uint16_t status, edc_err, *buf16; - int bits_corrected = 0; dev_dbg(doc->dev, "%s: page %08x\n", __func__, page); @@ -773,7 +772,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, /* If bitflips are reported, attempt to correct with ecc */ if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) { - bits_corrected = correct_data(mtd, buf, page); + int bits_corrected = correct_data(mtd, buf, page); if (bits_corrected == -EBADMSG) mtd->ecc_stats.failed++; else @@ -782,24 +781,24 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, } writew(0, docptr + DOC_DATAEND); - return bits_corrected; + return 0; } static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { return read_page(mtd, nand, buf, page, false); } static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { return read_page(mtd, nand, buf, page, true); } static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, - int page) + int page, int sndcmd) { struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; @@ -953,13 +952,13 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *nand, } static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { return write_page(mtd, nand, buf, false); } static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { return write_page(mtd, nand, buf, true); } @@ -1003,7 +1002,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) return -ENOMEM; read_page_prologue(mtd, g4_addr); - status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); + status = docg4_read_page(mtd, nand, buf, DOCG4_FACTORY_BBT_PAGE); if (status) goto exit; @@ -1080,7 +1079,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) /* write first page of block */ write_page_prologue(mtd, g4_addr); - docg4_write_page(mtd, nand, buf, 1); + docg4_write_page(mtd, nand, buf); ret = pageprog(mtd); if (!ret) mtd->ecc_stats.badblocks++; @@ -1193,7 +1192,8 @@ static void __init init_mtd_structs(struct mtd_info *mtd) nand->ecc.prepad = 8; nand->ecc.bytes = 8; nand->ecc.strength = DOCG4_T; - nand->options = NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE; + nand->options = + NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE | NAND_NO_AUTOINCR; nand->IO_ADDR_R = nand->IO_ADDR_W = doc->virtadr + DOC_IOSPACE_DATA; nand->controller = &nand->hwcontrol; spin_lock_init(&nand->controller->lock); diff --git a/trunk/drivers/mtd/nand/fsl_elbc_nand.c b/trunk/drivers/mtd/nand/fsl_elbc_nand.c index 784293806110..80b5264f0a32 100644 --- a/trunk/drivers/mtd/nand/fsl_elbc_nand.c +++ b/trunk/drivers/mtd/nand/fsl_elbc_nand.c @@ -75,7 +75,6 @@ struct fsl_elbc_fcm_ctrl { unsigned int use_mdr; /* Non zero if the MDR is to be set */ unsigned int oob; /* Non zero if operating on OOB data */ unsigned int counter; /* counter for the initializations */ - unsigned int max_bitflips; /* Saved during READ0 cmd */ }; /* These map to the positions used by the FCM hardware ECC generator */ @@ -254,8 +253,6 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) if (chip->ecc.mode != NAND_ECC_HW) return 0; - elbc_fcm_ctrl->max_bitflips = 0; - if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) { uint32_t lteccr = in_be32(&lbc->lteccr); /* @@ -265,16 +262,11 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) * bits 28-31 are uncorrectable errors, marked elsewhere. * for small page nand only 1 bit is used. * if the ELBC doesn't have the lteccr register it reads 0 - * FIXME: 4 bits can be corrected on NANDs with 2k pages, so - * count the number of sub-pages with bitflips and update - * ecc_stats.corrected accordingly. */ if (lteccr & 0x000F000F) out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */ - if (lteccr & 0x000F0000) { + if (lteccr & 0x000F0000) mtd->ecc_stats.corrected++; - elbc_fcm_ctrl->max_bitflips = 1; - } } return 0; @@ -746,28 +738,26 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) return 0; } -static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int fsl_elbc_read_page(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, + int page) { - struct fsl_elbc_mtd *priv = chip->priv; - struct fsl_lbc_ctrl *ctrl = priv->ctrl; - struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; - fsl_elbc_read_buf(mtd, buf, mtd->writesize); - if (oob_required) - fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) mtd->ecc_stats.failed++; - return elbc_fcm_ctrl->max_bitflips; + return 0; } /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) +static void fsl_elbc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf) { fsl_elbc_write_buf(mtd, buf, mtd->writesize); fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -805,7 +795,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->bbt_md = &bbt_mirror_descr; /* set up nand options */ - chip->options = NAND_NO_READRDY; + chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; chip->controller = &elbc_fcm_ctrl->controller; @@ -824,6 +814,11 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->ecc.size = 512; chip->ecc.bytes = 3; chip->ecc.strength = 1; + /* + * FIXME: can hardware ecc correct 4 bitflips if page size is + * 2k? Then does hardware report number of corrections for this + * case? If so, ecc_stats reporting needs to be fixed as well. + */ } else { /* otherwise fall back to default software ECC */ chip->ecc.mode = NAND_ECC_SOFT; diff --git a/trunk/drivers/mtd/nand/fsl_ifc_nand.c b/trunk/drivers/mtd/nand/fsl_ifc_nand.c index 9602c1b7e27e..c30ac7b83d28 100644 --- a/trunk/drivers/mtd/nand/fsl_ifc_nand.c +++ b/trunk/drivers/mtd/nand/fsl_ifc_nand.c @@ -63,7 +63,6 @@ struct fsl_ifc_nand_ctrl { unsigned int oob; /* Non zero if operating on OOB data */ unsigned int eccread; /* Non zero for a full-page ECC read */ unsigned int counter; /* counter for the initializations */ - unsigned int max_bitflips; /* Saved during READ0 cmd */ }; static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; @@ -263,8 +262,6 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER) dev_err(priv->dev, "NAND Flash Write Protect Error\n"); - nctrl->max_bitflips = 0; - if (nctrl->eccread) { int errors; int bufnum = nctrl->page & priv->bufnum_mask; @@ -293,9 +290,6 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) } mtd->ecc_stats.corrected += errors; - nctrl->max_bitflips = max_t(unsigned int, - nctrl->max_bitflips, - errors); } nctrl->eccread = 0; @@ -381,31 +375,21 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, return; + /* READID must read all 8 possible bytes */ case NAND_CMD_READID: - case NAND_CMD_PARAM: { - int timing = IFC_FIR_OP_RB; - if (command == NAND_CMD_PARAM) - timing = IFC_FIR_OP_RBCD; - out_be32(&ifc->ifc_nand.nand_fir0, (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | - (timing << IFC_NAND_FIR0_OP2_SHIFT)); + (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); out_be32(&ifc->ifc_nand.nand_fcr0, - command << IFC_NAND_FCR0_CMD0_SHIFT); - out_be32(&ifc->ifc_nand.row3, column); - - /* - * although currently it's 8 bytes for READID, we always read - * the maximum 256 bytes(for PARAM) - */ - out_be32(&ifc->ifc_nand.nand_fbcr, 256); - ifc_nand_ctrl->read_bytes = 256; + NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT); + /* 8 bytes for manuf, device and exts */ + out_be32(&ifc->ifc_nand.nand_fbcr, 8); + ifc_nand_ctrl->read_bytes = 8; set_addr(mtd, 0, 0, 0); fsl_ifc_run_command(mtd); return; - } /* ERASE1 stores the block and page address */ case NAND_CMD_ERASE1: @@ -698,16 +682,15 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) return nand_fsr | NAND_STATUS_WP; } -static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int fsl_ifc_read_page(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, int page) { struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; fsl_ifc_read_buf(mtd, buf, mtd->writesize); - if (oob_required) - fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) dev_err(priv->dev, "NAND Flash ECC Uncorrectable Error\n"); @@ -715,14 +698,15 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) mtd->ecc_stats.failed++; - return nctrl->max_bitflips; + return 0; } /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) +static void fsl_ifc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf) { fsl_ifc_write_buf(mtd, buf, mtd->writesize); fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -805,7 +789,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) out_be32(&ifc->ifc_nand.ncfgr, 0x0); /* set up nand options */ - chip->options = NAND_NO_READRDY; + chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; @@ -827,7 +811,6 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) /* Hardware generates ECC per 512 Bytes */ chip->ecc.size = 512; chip->ecc.bytes = 8; - chip->ecc.strength = 4; switch (csor & CSOR_NAND_PGS_MASK) { case CSOR_NAND_PGS_512: diff --git a/trunk/drivers/mtd/nand/fsmc_nand.c b/trunk/drivers/mtd/nand/fsmc_nand.c index 38d26240d8b1..1b8330e1155a 100644 --- a/trunk/drivers/mtd/nand/fsmc_nand.c +++ b/trunk/drivers/mtd/nand/fsmc_nand.c @@ -692,7 +692,6 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller expects OOB data read to chip->oob_poi * @page: page number to read * * This routine is needed for fsmc version 8 as reading from NAND chip has to be @@ -702,7 +701,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, * max of 8 bits) */ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct fsmc_nand_data *host = container_of(mtd, struct fsmc_nand_data, mtd); @@ -721,7 +720,6 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, */ uint16_t ecc_oob[7]; uint8_t *oob = (uint8_t *)&ecc_oob[0]; - unsigned int max_bitflips = 0; for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); @@ -750,15 +748,13 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, chip->ecc.calculate(mtd, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /* @@ -998,9 +994,9 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) return PTR_ERR(host->clk); } - ret = clk_prepare_enable(host->clk); + ret = clk_enable(host->clk); if (ret) - goto err_clk_prepare_enable; + goto err_clk_enable; /* * This device ID is actually a common AMBA ID as used on the @@ -1180,8 +1176,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) if (host->mode == USE_DMA_ACCESS) dma_release_channel(host->read_dma_chan); err_req_read_chnl: - clk_disable_unprepare(host->clk); -err_clk_prepare_enable: + clk_disable(host->clk); +err_clk_enable: clk_put(host->clk); return ret; } @@ -1202,7 +1198,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) dma_release_channel(host->write_dma_chan); dma_release_channel(host->read_dma_chan); } - clk_disable_unprepare(host->clk); + clk_disable(host->clk); clk_put(host->clk); } @@ -1214,7 +1210,7 @@ static int fsmc_nand_suspend(struct device *dev) { struct fsmc_nand_data *host = dev_get_drvdata(dev); if (host) - clk_disable_unprepare(host->clk); + clk_disable(host->clk); return 0; } @@ -1222,7 +1218,7 @@ static int fsmc_nand_resume(struct device *dev) { struct fsmc_nand_data *host = dev_get_drvdata(dev); if (host) { - clk_prepare_enable(host->clk); + clk_enable(host->clk); fsmc_nand_setup(host->regs_va, host->bank, host->nand.options & NAND_BUSWIDTH_16, host->dev_timings); diff --git a/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h b/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h index a0924515c396..4effb8c579db 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h +++ b/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h @@ -51,26 +51,15 @@ #define BP_BCH_FLASH0LAYOUT0_ECC0 12 #define BM_BCH_FLASH0LAYOUT0_ECC0 (0xf << BP_BCH_FLASH0LAYOUT0_ECC0) -#define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11 -#define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) -#define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \ - & MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \ - : (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \ - & BM_BCH_FLASH0LAYOUT0_ECC0) \ - ) +#define BF_BCH_FLASH0LAYOUT0_ECC0(v) \ + (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0) #define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE 0 #define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) -#define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ - (0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) -#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ - : ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ - ) +#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v) \ + (((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\ + & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) #define HW_BCH_FLASH0LAYOUT1 0x00000090 @@ -83,24 +72,13 @@ #define BP_BCH_FLASH0LAYOUT1_ECCN 12 #define BM_BCH_FLASH0LAYOUT1_ECCN (0xf << BP_BCH_FLASH0LAYOUT1_ECCN) -#define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11 -#define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) -#define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \ - & MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \ - : (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \ - & BM_BCH_FLASH0LAYOUT1_ECCN) \ - ) +#define BF_BCH_FLASH0LAYOUT1_ECCN(v) \ + (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN) #define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE 0 #define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) -#define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ - (0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) -#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ - : ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ - ) +#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v) \ + (((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ + & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) #endif diff --git a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index a1f43329ad43..e8ea7107932e 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "gpmi-nand.h" #include "gpmi-regs.h" @@ -36,8 +37,6 @@ struct timing_threshod timing_default_threshold = { .max_dll_delay_in_ns = 16, }; -#define MXS_SET_ADDR 0x4 -#define MXS_CLR_ADDR 0x8 /* * Clear the bit and poll it cleared. This is usually called with * a reset address and mask being either SFTRST(bit 31) or CLKGATE @@ -48,7 +47,7 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) int timeout = 0x400; /* clear the bit */ - writel(mask, addr + MXS_CLR_ADDR); + __mxs_clrl(mask, addr); /* * SFTRST needs 3 GPMI clocks to settle, the reference manual @@ -93,11 +92,11 @@ static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) goto error; /* clear CLKGATE */ - writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR); + __mxs_clrl(MODULE_CLKGATE, reset_addr); if (!just_enable) { /* set SFTRST to reset the block */ - writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR); + __mxs_setl(MODULE_SFTRST, reset_addr); udelay(1); /* poll CLKGATE becoming set */ @@ -224,13 +223,13 @@ int bch_set_geometry(struct gpmi_nand_data *this) /* Configure layout 0. */ writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count) | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size) - | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this) - | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this), + | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength) + | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size), r->bch_regs + HW_BCH_FLASH0LAYOUT0); writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size) - | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this) - | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this), + | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength) + | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size), r->bch_regs + HW_BCH_FLASH0LAYOUT1); /* Set *all* chip selects to use layout 0. */ @@ -256,12 +255,11 @@ static unsigned int ns_to_cycles(unsigned int time, return max(k, min); } -#define DEF_MIN_PROP_DELAY 5 -#define DEF_MAX_PROP_DELAY 9 /* Apply timing to current hardware conditions. */ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, struct gpmi_nfc_hardware_timing *hw) { + struct gpmi_nand_platform_data *pdata = this->pdata; struct timing_threshod *nfc = &timing_default_threshold; struct nand_chip *nand = &this->nand; struct nand_timing target = this->timing; @@ -278,8 +276,8 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, int ideal_sample_delay_in_ns; unsigned int sample_delay_factor; int tEYE; - unsigned int min_prop_delay_in_ns = DEF_MIN_PROP_DELAY; - unsigned int max_prop_delay_in_ns = DEF_MAX_PROP_DELAY; + unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns; + unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns; /* * If there are multiple chips, we need to relax the timings to allow @@ -805,8 +803,7 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip) if (GPMI_IS_MX23(this)) { mask = MX23_BM_GPMI_DEBUG_READY0 << chip; reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); - } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) { - /* MX28 shares the same R/B register as MX6Q. */ + } else if (GPMI_IS_MX28(this)) { mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip); reg = readl(r->gpmi_regs + HW_GPMI_STAT); } else diff --git a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index a05b7b444d4f..b68e04310bd8 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include "gpmi-nand.h" /* add our owner bbt descriptor */ @@ -389,7 +387,7 @@ static void release_bch_irq(struct gpmi_nand_data *this) static bool gpmi_dma_filter(struct dma_chan *chan, void *param) { struct gpmi_nand_data *this = param; - int dma_channel = (int)this->private; + struct resource *r = this->private; if (!mxs_dma_is_apbh(chan)) return false; @@ -401,7 +399,7 @@ static bool gpmi_dma_filter(struct dma_chan *chan, void *param) * for mx28 : MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7 * (These eight channels share the same IRQ!) */ - if (dma_channel == chan->chan_id) { + if (r->start <= chan->chan_id && chan->chan_id <= r->end) { chan->private = &this->dma_data; return true; } @@ -421,45 +419,57 @@ static void release_dma_channels(struct gpmi_nand_data *this) static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) { struct platform_device *pdev = this->pdev; - struct resource *r_dma; - struct device_node *dn; - int dma_channel; - unsigned int ret; - struct dma_chan *dma_chan; - dma_cap_mask_t mask; - - /* dma channel, we only use the first one. */ - dn = pdev->dev.of_node; - ret = of_property_read_u32(dn, "fsl,gpmi-dma-channel", &dma_channel); - if (ret) { - pr_err("unable to get DMA channel from dt.\n"); - goto acquire_err; - } - this->private = (void *)dma_channel; + struct gpmi_nand_platform_data *pdata = this->pdata; + struct resources *res = &this->resources; + struct resource *r, *r_dma; + unsigned int i; - /* gpmi dma interrupt */ + r = platform_get_resource_byname(pdev, IORESOURCE_DMA, + GPMI_NAND_DMA_CHANNELS_RES_NAME); r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ, GPMI_NAND_DMA_INTERRUPT_RES_NAME); - if (!r_dma) { + if (!r || !r_dma) { pr_err("Can't get resource for DMA\n"); - goto acquire_err; + return -ENXIO; } - this->dma_data.chan_irq = r_dma->start; - /* request dma channel */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); + /* used in gpmi_dma_filter() */ + this->private = r; + + for (i = r->start; i <= r->end; i++) { + struct dma_chan *dma_chan; + dma_cap_mask_t mask; - dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); - if (!dma_chan) { - pr_err("dma_request_channel failed.\n"); - goto acquire_err; + if (i - r->start >= pdata->max_chip_count) + break; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* get the DMA interrupt */ + if (r_dma->start == r_dma->end) { + /* only register the first. */ + if (i == r->start) + this->dma_data.chan_irq = r_dma->start; + else + this->dma_data.chan_irq = NO_IRQ; + } else + this->dma_data.chan_irq = r_dma->start + (i - r->start); + + dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); + if (!dma_chan) + goto acquire_err; + + /* fill the first empty item */ + this->dma_chans[i - r->start] = dma_chan; } - this->dma_chans[0] = dma_chan; + res->dma_low_channel = r->start; + res->dma_high_channel = i; return 0; acquire_err: + pr_err("Can't acquire DMA channel %u\n", i); release_dma_channels(this); return -EINVAL; } @@ -841,7 +851,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this, } static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct gpmi_nand_data *this = chip->priv; struct bch_geometry *nfc_geo = &this->bch_geometry; @@ -907,31 +917,28 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, mtd->ecc_stats.corrected += corrected; } - if (oob_required) { - /* - * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() - * for details about our policy for delivering the OOB. - * - * We fill the caller's buffer with set bits, and then copy the - * block mark to th caller's buffer. Note that, if block mark - * swapping was necessary, it has already been done, so we can - * rely on the first byte of the auxiliary buffer to contain - * the block mark. - */ - memset(chip->oob_poi, ~0, mtd->oobsize); - chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; + /* + * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() for + * details about our policy for delivering the OOB. + * + * We fill the caller's buffer with set bits, and then copy the block + * mark to th caller's buffer. Note that, if block mark swapping was + * necessary, it has already been done, so we can rely on the first + * byte of the auxiliary buffer to contain the block mark. + */ + memset(chip->oob_poi, ~0, mtd->oobsize); + chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; - read_page_swap_end(this, buf, mtd->writesize, - this->payload_virt, this->payload_phys, - nfc_geo->payload_size, - payload_virt, payload_phys); - } + read_page_swap_end(this, buf, mtd->writesize, + this->payload_virt, this->payload_phys, + nfc_geo->payload_size, + payload_virt, payload_phys); exit_nfc: return ret; } -static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) +static void gpmi_ecc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) { struct gpmi_nand_data *this = chip->priv; struct bch_geometry *nfc_geo = &this->bch_geometry; @@ -1070,7 +1077,7 @@ static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, * this driver. */ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { struct gpmi_nand_data *this = chip->priv; @@ -1093,7 +1100,11 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, chip->oob_poi[0] = chip->read_byte(mtd); } - return 0; + /* + * Return true, indicating that the next call to this function must send + * a command. + */ + return true; } static int @@ -1307,7 +1318,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) /* Write the first page of the current stride. */ dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); - chip->ecc.write_page_raw(mtd, chip, buffer, 0); + chip->ecc.write_page_raw(mtd, chip, buffer); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); /* Wait for the write to finish. */ @@ -1433,10 +1444,6 @@ static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this) if (ret) return ret; - /* Adjust the ECC strength according to the chip. */ - this->nand.ecc.strength = this->bch_geometry.ecc_strength; - this->mtd.ecc_strength = this->bch_geometry.ecc_strength; - /* NAND boot init, depends on the gpmi_set_geometry(). */ return nand_boot_init(this); } @@ -1464,9 +1471,9 @@ void gpmi_nfc_exit(struct gpmi_nand_data *this) static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) { + struct gpmi_nand_platform_data *pdata = this->pdata; struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; - struct mtd_part_parser_data ppdata = {}; int ret; /* init current chip */ @@ -1495,7 +1502,6 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) chip->options |= NAND_NO_SUBPAGE_WRITE; chip->ecc.mode = NAND_ECC_HW; chip->ecc.size = 1; - chip->ecc.strength = 8; chip->ecc.layout = &gpmi_hw_ecclayout; /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */ @@ -1505,14 +1511,14 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) if (ret) goto err_out; - ret = nand_scan(mtd, 1); + ret = nand_scan(mtd, pdata->max_chip_count); if (ret) { pr_err("Chip scan failed\n"); goto err_out; } - ppdata.of_node = this->pdev->dev.of_node; - ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_parse_register(mtd, NULL, NULL, + pdata->partitions, pdata->partition_count); if (ret) goto err_out; return 0; @@ -1522,41 +1528,12 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) return ret; } -static const struct platform_device_id gpmi_ids[] = { - { .name = "imx23-gpmi-nand", .driver_data = IS_MX23, }, - { .name = "imx28-gpmi-nand", .driver_data = IS_MX28, }, - { .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, }, - {}, -}; - -static const struct of_device_id gpmi_nand_id_table[] = { - { - .compatible = "fsl,imx23-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX23] - }, { - .compatible = "fsl,imx28-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX28] - }, { - .compatible = "fsl,imx6q-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX6Q] - }, {} -}; -MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); - static int __devinit gpmi_nand_probe(struct platform_device *pdev) { + struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data; struct gpmi_nand_data *this; - const struct of_device_id *of_id; int ret; - of_id = of_match_device(gpmi_nand_id_table, &pdev->dev); - if (of_id) { - pdev->id_entry = of_id->data; - } else { - pr_err("Failed to find the right device id.\n"); - return -ENOMEM; - } - this = kzalloc(sizeof(*this), GFP_KERNEL); if (!this) { pr_err("Failed to allocate per-device memory\n"); @@ -1566,6 +1543,13 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) platform_set_drvdata(pdev, this); this->pdev = pdev; this->dev = &pdev->dev; + this->pdata = pdata; + + if (pdata->platform_init) { + ret = pdata->platform_init(); + if (ret) + goto platform_init_error; + } ret = acquire_resources(this); if (ret) @@ -1583,6 +1567,7 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) exit_nfc_init: release_resources(this); +platform_init_error: exit_acquire_resources: platform_set_drvdata(pdev, NULL); kfree(this); @@ -1600,10 +1585,19 @@ static int __exit gpmi_nand_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id gpmi_ids[] = { + { + .name = "imx23-gpmi-nand", + .driver_data = IS_MX23, + }, { + .name = "imx28-gpmi-nand", + .driver_data = IS_MX28, + }, {}, +}; + static struct platform_driver gpmi_nand_driver = { .driver = { .name = "gpmi-nand", - .of_match_table = gpmi_nand_id_table, }, .probe = gpmi_nand_probe, .remove = __exit_p(gpmi_nand_remove), diff --git a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index ce5daa160920..ec6180d4ff8f 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h @@ -266,10 +266,8 @@ extern int gpmi_read_page(struct gpmi_nand_data *, #define STATUS_UNCORRECTABLE 0xfe /* Use the platform_id to distinguish different Archs. */ -#define IS_MX23 0x0 -#define IS_MX28 0x1 -#define IS_MX6Q 0x2 +#define IS_MX23 0x1 +#define IS_MX28 0x2 #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) -#define GPMI_IS_MX6Q(x) ((x)->pdev->id_entry->driver_data == IS_MX6Q) #endif diff --git a/trunk/drivers/mtd/nand/h1910.c b/trunk/drivers/mtd/nand/h1910.c index 50166e93ba96..9bf5ce5fa22d 100644 --- a/trunk/drivers/mtd/nand/h1910.c +++ b/trunk/drivers/mtd/nand/h1910.c @@ -124,6 +124,7 @@ static int __init h1910_init(void) /* 15 us command delay time */ this->chip_delay = 50; this->ecc.mode = NAND_ECC_SOFT; + this->options = NAND_NO_AUTOINCR; /* Scan to find existence of the device */ if (nand_scan(h1910_nand_mtd, 1)) { diff --git a/trunk/drivers/mtd/nand/jz4740_nand.c b/trunk/drivers/mtd/nand/jz4740_nand.c index a6fa884ae49b..e4147e8acb7c 100644 --- a/trunk/drivers/mtd/nand/jz4740_nand.c +++ b/trunk/drivers/mtd/nand/jz4740_nand.c @@ -332,7 +332,11 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) chip->ecc.mode = NAND_ECC_HW_OOB_FIRST; chip->ecc.size = 512; chip->ecc.bytes = 9; - chip->ecc.strength = 4; + chip->ecc.strength = 2; + /* + * FIXME: ecc_strength value of 2 bits per 512 bytes of data is a + * conservative guess, given 9 ecc bytes and reed-solomon alg. + */ if (pdata) chip->ecc.layout = pdata->ecc_layout; diff --git a/trunk/drivers/mtd/nand/mpc5121_nfc.c b/trunk/drivers/mtd/nand/mpc5121_nfc.c index c259c24d7986..c240cf1af961 100644 --- a/trunk/drivers/mtd/nand/mpc5121_nfc.c +++ b/trunk/drivers/mtd/nand/mpc5121_nfc.c @@ -734,6 +734,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) chip->write_buf = mpc5121_nfc_write_buf; chip->verify_buf = mpc5121_nfc_verify_buf; chip->select_chip = mpc5121_nfc_select_chip; + chip->options = NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; chip->ecc.mode = NAND_ECC_SOFT; diff --git a/trunk/drivers/mtd/nand/mxc_nand.c b/trunk/drivers/mtd/nand/mxc_nand.c index c58e6a93f445..9e374e9bd296 100644 --- a/trunk/drivers/mtd/nand/mxc_nand.c +++ b/trunk/drivers/mtd/nand/mxc_nand.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include #include @@ -142,47 +140,13 @@ #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) -struct mxc_nand_host; - -struct mxc_nand_devtype_data { - void (*preset)(struct mtd_info *); - void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); - void (*send_addr)(struct mxc_nand_host *, uint16_t, int); - void (*send_page)(struct mtd_info *, unsigned int); - void (*send_read_id)(struct mxc_nand_host *); - uint16_t (*get_dev_status)(struct mxc_nand_host *); - int (*check_int)(struct mxc_nand_host *); - void (*irq_control)(struct mxc_nand_host *, int); - u32 (*get_ecc_status)(struct mxc_nand_host *); - struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k; - void (*select_chip)(struct mtd_info *mtd, int chip); - int (*correct_data)(struct mtd_info *mtd, u_char *dat, - u_char *read_ecc, u_char *calc_ecc); - - /* - * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked - * (CONFIG1:INT_MSK is set). To handle this the driver uses - * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK - */ - int irqpending_quirk; - int needs_ip; - - size_t regs_offset; - size_t spare0_offset; - size_t axi_offset; - - int spare_len; - int eccbytes; - int eccsize; -}; - struct mxc_nand_host { struct mtd_info mtd; struct nand_chip nand; struct device *dev; - void __iomem *spare0; - void __iomem *main_area0; + void *spare0; + void *main_area0; void __iomem *base; void __iomem *regs; @@ -199,9 +163,16 @@ struct mxc_nand_host { uint8_t *data_buf; unsigned int buf_start; - - const struct mxc_nand_devtype_data *devtype_data; - struct mxc_nand_platform_data pdata; + int spare_len; + + void (*preset)(struct mtd_info *); + void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); + void (*send_addr)(struct mxc_nand_host *, uint16_t, int); + void (*send_page)(struct mtd_info *, unsigned int); + void (*send_read_id)(struct mxc_nand_host *); + uint16_t (*get_dev_status)(struct mxc_nand_host *); + int (*check_int)(struct mxc_nand_host *); + void (*irq_control)(struct mxc_nand_host *, int); }; /* OOB placement block for use with hardware ecc generation */ @@ -271,7 +242,21 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { } }; -static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL }; +static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; + +static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) +{ + struct mxc_nand_host *host = dev_id; + + if (!host->check_int(host)) + return IRQ_NONE; + + host->irq_control(host, 0); + + complete(&host->op_completion); + + return IRQ_HANDLED; +} static int check_int_v3(struct mxc_nand_host *host) { @@ -295,12 +280,26 @@ static int check_int_v1_v2(struct mxc_nand_host *host) if (!(tmp & NFC_V1_V2_CONFIG2_INT)) return 0; - if (!host->devtype_data->irqpending_quirk) + if (!cpu_is_mx21()) writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); return 1; } +/* + * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit + * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the + * driver can enable/disable the irq line rather than simply masking the + * interrupts. + */ +static void irq_control_mx21(struct mxc_nand_host *host, int activate) +{ + if (activate) + enable_irq(host->irq); + else + disable_irq_nosync(host->irq); +} + static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) { uint16_t tmp; @@ -329,47 +328,6 @@ static void irq_control_v3(struct mxc_nand_host *host, int activate) writel(tmp, NFC_V3_CONFIG2); } -static void irq_control(struct mxc_nand_host *host, int activate) -{ - if (host->devtype_data->irqpending_quirk) { - if (activate) - enable_irq(host->irq); - else - disable_irq_nosync(host->irq); - } else { - host->devtype_data->irq_control(host, activate); - } -} - -static u32 get_ecc_status_v1(struct mxc_nand_host *host) -{ - return readw(NFC_V1_V2_ECC_STATUS_RESULT); -} - -static u32 get_ecc_status_v2(struct mxc_nand_host *host) -{ - return readl(NFC_V1_V2_ECC_STATUS_RESULT); -} - -static u32 get_ecc_status_v3(struct mxc_nand_host *host) -{ - return readl(NFC_V3_ECC_STATUS_RESULT); -} - -static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) -{ - struct mxc_nand_host *host = dev_id; - - if (!host->devtype_data->check_int(host)) - return IRQ_NONE; - - irq_control(host, 0); - - complete(&host->op_completion); - - return IRQ_HANDLED; -} - /* This function polls the NANDFC to wait for the basic operation to * complete by checking the INT bit of config2 register. */ @@ -378,14 +336,14 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) int max_retries = 8000; if (useirq) { - if (!host->devtype_data->check_int(host)) { + if (!host->check_int(host)) { INIT_COMPLETION(host->op_completion); - irq_control(host, 1); + host->irq_control(host, 1); wait_for_completion(&host->op_completion); } } else { while (max_retries-- > 0) { - if (host->devtype_data->check_int(host)) + if (host->check_int(host)) break; udelay(1); @@ -416,7 +374,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) writew(cmd, NFC_V1_V2_FLASH_CMD); writew(NFC_CMD, NFC_V1_V2_CONFIG2); - if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) { + if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { int max_retries = 100; /* Reset completion is indicated by NFC_CONFIG2 */ /* being set to 0 */ @@ -475,27 +433,13 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops) wait_op_done(host, false); } -static void send_page_v2(struct mtd_info *mtd, unsigned int ops) -{ - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - - /* NANDFC buffer 0 is used for page read/write */ - writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); - - writew(ops, NFC_V1_V2_CONFIG2); - - /* Wait for operation to complete */ - wait_op_done(host, true); -} - -static void send_page_v1(struct mtd_info *mtd, unsigned int ops) +static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; int bufs, i; - if (mtd->writesize > 512) + if (nfc_is_v1() && mtd->writesize > 512) bufs = 4; else bufs = 1; @@ -519,7 +463,7 @@ static void send_read_id_v3(struct mxc_nand_host *host) wait_op_done(host, true); - memcpy_fromio(host->data_buf, host->main_area0, 16); + memcpy(host->data_buf, host->main_area0, 16); } /* Request the NANDFC to perform a read of the NAND device ID. */ @@ -535,7 +479,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) /* Wait for operation to complete */ wait_op_done(host, true); - memcpy_fromio(host->data_buf, host->main_area0, 16); + memcpy(host->data_buf, host->main_area0, 16); if (this->options & NAND_BUSWIDTH_16) { /* compress the ID info */ @@ -611,7 +555,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = get_ecc_status_v1(host); + uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); @@ -636,7 +580,10 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, no_subpages = mtd->writesize >> 9; - ecc_stat = host->devtype_data->get_ecc_status(host); + if (nfc_is_v21()) + ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); + else + ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); do { err = ecc_stat & ecc_bit_mask; @@ -669,7 +616,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) /* Check for status request */ if (host->status_request) - return host->devtype_data->get_dev_status(host) & 0xFF; + return host->get_dev_status(host) & 0xFF; ret = *(uint8_t *)(host->data_buf + host->buf_start); host->buf_start++; @@ -735,7 +682,7 @@ static int mxc_nand_verify_buf(struct mtd_info *mtd, /* This function is used by upper layer for select and * deselect of the NAND chip */ -static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) +static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; @@ -754,30 +701,11 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) clk_prepare_enable(host->clk); host->clk_act = 1; } -} -static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) -{ - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - - if (chip == -1) { - /* Disable the NFC clock */ - if (host->clk_act) { - clk_disable(host->clk); - host->clk_act = 0; - } - return; - } - - if (!host->clk_act) { - /* Enable the NFC clock */ - clk_enable(host->clk); - host->clk_act = 1; + if (nfc_is_v21()) { + host->active_cs = chip; + writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); } - - host->active_cs = chip; - writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); } /* @@ -790,23 +718,23 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) u16 i, j; u16 n = mtd->writesize >> 9; u8 *d = host->data_buf + mtd->writesize; - u8 __iomem *s = host->spare0; - u16 t = host->devtype_data->spare_len; + u8 *s = host->spare0; + u16 t = host->spare_len; j = (mtd->oobsize / n >> 1) << 1; if (bfrom) { for (i = 0; i < n - 1; i++) - memcpy_fromio(d + i * j, s + i * t, j); + memcpy(d + i * j, s + i * t, j); /* the last section */ - memcpy_fromio(d + i * j, s + i * t, mtd->oobsize - i * j); + memcpy(d + i * j, s + i * t, mtd->oobsize - i * j); } else { for (i = 0; i < n - 1; i++) - memcpy_toio(&s[i * t], &d[i * j], j); + memcpy(&s[i * t], &d[i * j], j); /* the last section */ - memcpy_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j); + memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j); } } @@ -823,44 +751,34 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) * perform a read/write buf operation, the saved column * address is used to index into the full page. */ - host->devtype_data->send_addr(host, 0, page_addr == -1); + host->send_addr(host, 0, page_addr == -1); if (mtd->writesize > 512) /* another col addr cycle for 2k page */ - host->devtype_data->send_addr(host, 0, false); + host->send_addr(host, 0, false); } /* Write out page address, if necessary */ if (page_addr != -1) { /* paddr_0 - p_addr_7 */ - host->devtype_data->send_addr(host, (page_addr & 0xff), false); + host->send_addr(host, (page_addr & 0xff), false); if (mtd->writesize > 512) { if (mtd->size >= 0x10000000) { /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, - false); - host->devtype_data->send_addr(host, - (page_addr >> 16) & 0xff, - true); + host->send_addr(host, (page_addr >> 8) & 0xff, false); + host->send_addr(host, (page_addr >> 16) & 0xff, true); } else /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, true); + host->send_addr(host, (page_addr >> 8) & 0xff, true); } else { /* One more address cycle for higher density devices */ if (mtd->size >= 0x4000000) { /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, - false); - host->devtype_data->send_addr(host, - (page_addr >> 16) & 0xff, - true); + host->send_addr(host, (page_addr >> 8) & 0xff, false); + host->send_addr(host, (page_addr >> 16) & 0xff, true); } else /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, true); + host->send_addr(host, (page_addr >> 8) & 0xff, true); } } } @@ -882,35 +800,7 @@ static int get_eccsize(struct mtd_info *mtd) return 8; } -static void preset_v1(struct mtd_info *mtd) -{ - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - uint16_t config1 = 0; - - if (nand_chip->ecc.mode == NAND_ECC_HW) - config1 |= NFC_V1_V2_CONFIG1_ECC_EN; - - if (!host->devtype_data->irqpending_quirk) - config1 |= NFC_V1_V2_CONFIG1_INT_MSK; - - host->eccsize = 1; - - writew(config1, NFC_V1_V2_CONFIG1); - /* preset operation */ - - /* Unlock the internal RAM Buffer */ - writew(0x2, NFC_V1_V2_CONFIG); - - /* Blocks to be unlocked */ - writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); - writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); - - /* Unlock Block Command for given address range */ - writew(0x4, NFC_V1_V2_WRPROT); -} - -static void preset_v2(struct mtd_info *mtd) +static void preset_v1_v2(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; @@ -919,12 +809,13 @@ static void preset_v2(struct mtd_info *mtd) if (nand_chip->ecc.mode == NAND_ECC_HW) config1 |= NFC_V1_V2_CONFIG1_ECC_EN; - config1 |= NFC_V2_CONFIG1_FP_INT; + if (nfc_is_v21()) + config1 |= NFC_V2_CONFIG1_FP_INT; - if (!host->devtype_data->irqpending_quirk) + if (!cpu_is_mx21()) config1 |= NFC_V1_V2_CONFIG1_INT_MSK; - if (mtd->writesize) { + if (nfc_is_v21() && mtd->writesize) { uint16_t pages_per_block = mtd->erasesize / mtd->writesize; host->eccsize = get_eccsize(mtd); @@ -943,14 +834,20 @@ static void preset_v2(struct mtd_info *mtd) writew(0x2, NFC_V1_V2_CONFIG); /* Blocks to be unlocked */ - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); + if (nfc_is_v21()) { + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); + } else if (nfc_is_v1()) { + writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); + writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); + } else + BUG(); /* Unlock Block Command for given address range */ writew(0x4, NFC_V1_V2_WRPROT); @@ -1040,15 +937,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, /* Command pre-processing step */ switch (command) { case NAND_CMD_RESET: - host->devtype_data->preset(mtd); - host->devtype_data->send_cmd(host, command, false); + host->preset(mtd); + host->send_cmd(host, command, false); break; case NAND_CMD_STATUS: host->buf_start = 0; host->status_request = true; - host->devtype_data->send_cmd(host, command, true); + host->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -1061,16 +958,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, command = NAND_CMD_READ0; /* only READ0 is valid */ - host->devtype_data->send_cmd(host, command, false); + host->send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); if (mtd->writesize > 512) - host->devtype_data->send_cmd(host, - NAND_CMD_READSTART, true); + host->send_cmd(host, NAND_CMD_READSTART, true); - host->devtype_data->send_page(mtd, NFC_OUTPUT); + host->send_page(mtd, NFC_OUTPUT); - memcpy_fromio(host->data_buf, host->main_area0, mtd->writesize); + memcpy(host->data_buf, host->main_area0, mtd->writesize); copy_spare(mtd, true); break; @@ -1081,28 +977,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, host->buf_start = column; - host->devtype_data->send_cmd(host, command, false); + host->send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); break; case NAND_CMD_PAGEPROG: - memcpy_toio(host->main_area0, host->data_buf, mtd->writesize); + memcpy(host->main_area0, host->data_buf, mtd->writesize); copy_spare(mtd, false); - host->devtype_data->send_page(mtd, NFC_INPUT); - host->devtype_data->send_cmd(host, command, true); + host->send_page(mtd, NFC_INPUT); + host->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); break; case NAND_CMD_READID: - host->devtype_data->send_cmd(host, command, true); + host->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); - host->devtype_data->send_read_id(host); + host->send_read_id(host); host->buf_start = column; break; case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: - host->devtype_data->send_cmd(host, command, false); + host->send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -1136,191 +1032,15 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = mirror_pattern, }; -/* v1 + irqpending_quirk: i.MX21 */ -static const struct mxc_nand_devtype_data imx21_nand_devtype_data = { - .preset = preset_v1, - .send_cmd = send_cmd_v1_v2, - .send_addr = send_addr_v1_v2, - .send_page = send_page_v1, - .send_read_id = send_read_id_v1_v2, - .get_dev_status = get_dev_status_v1_v2, - .check_int = check_int_v1_v2, - .irq_control = irq_control_v1_v2, - .get_ecc_status = get_ecc_status_v1, - .ecclayout_512 = &nandv1_hw_eccoob_smallpage, - .ecclayout_2k = &nandv1_hw_eccoob_largepage, - .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ - .select_chip = mxc_nand_select_chip_v1_v3, - .correct_data = mxc_nand_correct_data_v1, - .irqpending_quirk = 1, - .needs_ip = 0, - .regs_offset = 0xe00, - .spare0_offset = 0x800, - .spare_len = 16, - .eccbytes = 3, - .eccsize = 1, -}; - -/* v1 + !irqpending_quirk: i.MX27, i.MX31 */ -static const struct mxc_nand_devtype_data imx27_nand_devtype_data = { - .preset = preset_v1, - .send_cmd = send_cmd_v1_v2, - .send_addr = send_addr_v1_v2, - .send_page = send_page_v1, - .send_read_id = send_read_id_v1_v2, - .get_dev_status = get_dev_status_v1_v2, - .check_int = check_int_v1_v2, - .irq_control = irq_control_v1_v2, - .get_ecc_status = get_ecc_status_v1, - .ecclayout_512 = &nandv1_hw_eccoob_smallpage, - .ecclayout_2k = &nandv1_hw_eccoob_largepage, - .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ - .select_chip = mxc_nand_select_chip_v1_v3, - .correct_data = mxc_nand_correct_data_v1, - .irqpending_quirk = 0, - .needs_ip = 0, - .regs_offset = 0xe00, - .spare0_offset = 0x800, - .axi_offset = 0, - .spare_len = 16, - .eccbytes = 3, - .eccsize = 1, -}; - -/* v21: i.MX25, i.MX35 */ -static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { - .preset = preset_v2, - .send_cmd = send_cmd_v1_v2, - .send_addr = send_addr_v1_v2, - .send_page = send_page_v2, - .send_read_id = send_read_id_v1_v2, - .get_dev_status = get_dev_status_v1_v2, - .check_int = check_int_v1_v2, - .irq_control = irq_control_v1_v2, - .get_ecc_status = get_ecc_status_v2, - .ecclayout_512 = &nandv2_hw_eccoob_smallpage, - .ecclayout_2k = &nandv2_hw_eccoob_largepage, - .ecclayout_4k = &nandv2_hw_eccoob_4k, - .select_chip = mxc_nand_select_chip_v2, - .correct_data = mxc_nand_correct_data_v2_v3, - .irqpending_quirk = 0, - .needs_ip = 0, - .regs_offset = 0x1e00, - .spare0_offset = 0x1000, - .axi_offset = 0, - .spare_len = 64, - .eccbytes = 9, - .eccsize = 0, -}; - -/* v3: i.MX51, i.MX53 */ -static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { - .preset = preset_v3, - .send_cmd = send_cmd_v3, - .send_addr = send_addr_v3, - .send_page = send_page_v3, - .send_read_id = send_read_id_v3, - .get_dev_status = get_dev_status_v3, - .check_int = check_int_v3, - .irq_control = irq_control_v3, - .get_ecc_status = get_ecc_status_v3, - .ecclayout_512 = &nandv2_hw_eccoob_smallpage, - .ecclayout_2k = &nandv2_hw_eccoob_largepage, - .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ - .select_chip = mxc_nand_select_chip_v1_v3, - .correct_data = mxc_nand_correct_data_v2_v3, - .irqpending_quirk = 0, - .needs_ip = 1, - .regs_offset = 0, - .spare0_offset = 0x1000, - .axi_offset = 0x1e00, - .spare_len = 64, - .eccbytes = 0, - .eccsize = 0, -}; - -#ifdef CONFIG_OF_MTD -static const struct of_device_id mxcnd_dt_ids[] = { - { - .compatible = "fsl,imx21-nand", - .data = &imx21_nand_devtype_data, - }, { - .compatible = "fsl,imx27-nand", - .data = &imx27_nand_devtype_data, - }, { - .compatible = "fsl,imx25-nand", - .data = &imx25_nand_devtype_data, - }, { - .compatible = "fsl,imx51-nand", - .data = &imx51_nand_devtype_data, - }, - { /* sentinel */ } -}; - -static int __init mxcnd_probe_dt(struct mxc_nand_host *host) -{ - struct device_node *np = host->dev->of_node; - struct mxc_nand_platform_data *pdata = &host->pdata; - const struct of_device_id *of_id = - of_match_device(mxcnd_dt_ids, host->dev); - int buswidth; - - if (!np) - return 1; - - if (of_get_nand_ecc_mode(np) >= 0) - pdata->hw_ecc = 1; - - pdata->flash_bbt = of_get_nand_on_flash_bbt(np); - - buswidth = of_get_nand_bus_width(np); - if (buswidth < 0) - return buswidth; - - pdata->width = buswidth / 8; - - host->devtype_data = of_id->data; - - return 0; -} -#else -static int __init mxcnd_probe_dt(struct mxc_nand_host *host) -{ - return 1; -} -#endif - -static int __init mxcnd_probe_pdata(struct mxc_nand_host *host) -{ - struct mxc_nand_platform_data *pdata = host->dev->platform_data; - - if (!pdata) - return -ENODEV; - - host->pdata = *pdata; - - if (nfc_is_v1()) { - if (cpu_is_mx21()) - host->devtype_data = &imx21_nand_devtype_data; - else - host->devtype_data = &imx27_nand_devtype_data; - } else if (nfc_is_v21()) { - host->devtype_data = &imx25_nand_devtype_data; - } else if (nfc_is_v3_2()) { - host->devtype_data = &imx51_nand_devtype_data; - } else - BUG(); - - return 0; -} - static int __init mxcnd_probe(struct platform_device *pdev) { struct nand_chip *this; struct mtd_info *mtd; + struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; struct mxc_nand_host *host; struct resource *res; int err = 0; + struct nand_ecclayout *oob_smallpage, *oob_largepage; /* Allocate memory for MTD device structure and private data */ host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + @@ -1345,6 +1065,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->priv = host; this->dev_ready = mxc_nand_dev_ready; this->cmdfunc = mxc_nand_command; + this->select_chip = mxc_nand_select_chip; this->read_byte = mxc_nand_read_byte; this->read_word = mxc_nand_read_word; this->write_buf = mxc_nand_write_buf; @@ -1374,26 +1095,36 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->main_area0 = host->base; - err = mxcnd_probe_dt(host); - if (err > 0) - err = mxcnd_probe_pdata(host); - if (err < 0) - goto eirq; - - if (host->devtype_data->regs_offset) - host->regs = host->base + host->devtype_data->regs_offset; - host->spare0 = host->base + host->devtype_data->spare0_offset; - if (host->devtype_data->axi_offset) - host->regs_axi = host->base + host->devtype_data->axi_offset; - - this->ecc.bytes = host->devtype_data->eccbytes; - host->eccsize = host->devtype_data->eccsize; - - this->select_chip = host->devtype_data->select_chip; - this->ecc.size = 512; - this->ecc.layout = host->devtype_data->ecclayout_512; + if (nfc_is_v1() || nfc_is_v21()) { + host->preset = preset_v1_v2; + host->send_cmd = send_cmd_v1_v2; + host->send_addr = send_addr_v1_v2; + host->send_page = send_page_v1_v2; + host->send_read_id = send_read_id_v1_v2; + host->get_dev_status = get_dev_status_v1_v2; + host->check_int = check_int_v1_v2; + if (cpu_is_mx21()) + host->irq_control = irq_control_mx21; + else + host->irq_control = irq_control_v1_v2; + } - if (host->devtype_data->needs_ip) { + if (nfc_is_v21()) { + host->regs = host->base + 0x1e00; + host->spare0 = host->base + 0x1000; + host->spare_len = 64; + oob_smallpage = &nandv2_hw_eccoob_smallpage; + oob_largepage = &nandv2_hw_eccoob_largepage; + this->ecc.bytes = 9; + } else if (nfc_is_v1()) { + host->regs = host->base + 0xe00; + host->spare0 = host->base + 0x800; + host->spare_len = 16; + oob_smallpage = &nandv1_hw_eccoob_smallpage; + oob_largepage = &nandv1_hw_eccoob_largepage; + this->ecc.bytes = 3; + host->eccsize = 1; + } else if (nfc_is_v3_2()) { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { err = -ENODEV; @@ -1404,22 +1135,42 @@ static int __init mxcnd_probe(struct platform_device *pdev) err = -ENOMEM; goto eirq; } - } + host->regs_axi = host->base + 0x1e00; + host->spare0 = host->base + 0x1000; + host->spare_len = 64; + host->preset = preset_v3; + host->send_cmd = send_cmd_v3; + host->send_addr = send_addr_v3; + host->send_page = send_page_v3; + host->send_read_id = send_read_id_v3; + host->check_int = check_int_v3; + host->get_dev_status = get_dev_status_v3; + host->irq_control = irq_control_v3; + oob_smallpage = &nandv2_hw_eccoob_smallpage; + oob_largepage = &nandv2_hw_eccoob_largepage; + } else + BUG(); + + this->ecc.size = 512; + this->ecc.layout = oob_smallpage; - if (host->pdata.hw_ecc) { + if (pdata->hw_ecc) { this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; - this->ecc.correct = host->devtype_data->correct_data; + if (nfc_is_v1()) + this->ecc.correct = mxc_nand_correct_data_v1; + else + this->ecc.correct = mxc_nand_correct_data_v2_v3; this->ecc.mode = NAND_ECC_HW; } else { this->ecc.mode = NAND_ECC_SOFT; } - /* NAND bus width determines access functions used by upper layer */ - if (host->pdata.width == 2) + /* NAND bus width determines access funtions used by upper layer */ + if (pdata->width == 2) this->options |= NAND_BUSWIDTH_16; - if (host->pdata.flash_bbt) { + if (pdata->flash_bbt) { this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; /* update flash based bbt */ @@ -1431,25 +1182,28 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->irq = platform_get_irq(pdev, 0); /* - * Use host->devtype_data->irq_control() here instead of irq_control() - * because we must not disable_irq_nosync without having requested the - * irq. + * mask the interrupt. For i.MX21 explicitely call + * irq_control_v1_v2 to use the mask bit. We can't call + * disable_irq_nosync() for an interrupt we do not own yet. */ - host->devtype_data->irq_control(host, 0); + if (cpu_is_mx21()) + irq_control_v1_v2(host, 0); + else + host->irq_control(host, 0); err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); if (err) goto eirq; + host->irq_control(host, 0); + /* - * Now that we "own" the interrupt make sure the interrupt mask bit is - * cleared on i.MX21. Otherwise we can't read the interrupt status bit - * on this machine. + * Now that the interrupt is disabled make sure the interrupt + * mask bit is cleared on i.MX21. Otherwise we can't read + * the interrupt status bit on this machine. */ - if (host->devtype_data->irqpending_quirk) { - disable_irq_nosync(host->irq); - host->devtype_data->irq_control(host, 1); - } + if (cpu_is_mx21()) + irq_control_v1_v2(host, 1); /* first scan to find the device and get the page size */ if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { @@ -1458,12 +1212,18 @@ static int __init mxcnd_probe(struct platform_device *pdev) } /* Call preset again, with correct writesize this time */ - host->devtype_data->preset(mtd); + host->preset(mtd); if (mtd->writesize == 2048) - this->ecc.layout = host->devtype_data->ecclayout_2k; - else if (mtd->writesize == 4096) - this->ecc.layout = host->devtype_data->ecclayout_4k; + this->ecc.layout = oob_largepage; + if (nfc_is_v21() && mtd->writesize == 4096) + this->ecc.layout = &nandv2_hw_eccoob_4k; + + /* second phase scan */ + if (nand_scan_tail(mtd)) { + err = -ENXIO; + goto escan; + } if (this->ecc.mode == NAND_ECC_HW) { if (nfc_is_v1()) @@ -1472,19 +1232,9 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->ecc.strength = (host->eccsize == 4) ? 4 : 8; } - /* second phase scan */ - if (nand_scan_tail(mtd)) { - err = -ENXIO; - goto escan; - } - /* Register the partitions */ - mtd_device_parse_register(mtd, part_probes, - &(struct mtd_part_parser_data){ - .of_node = pdev->dev.of_node, - }, - host->pdata.parts, - host->pdata.nr_parts); + mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts, + pdata->nr_parts); platform_set_drvdata(pdev, host); @@ -1525,8 +1275,6 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) static struct platform_driver mxcnd_driver = { .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(mxcnd_dt_ids), }, .remove = __devexit_p(mxcnd_remove), }; diff --git a/trunk/drivers/mtd/nand/nand_base.c b/trunk/drivers/mtd/nand/nand_base.c index d47586cf64ce..47b19c0bb070 100644 --- a/trunk/drivers/mtd/nand/nand_base.c +++ b/trunk/drivers/mtd/nand/nand_base.c @@ -1066,17 +1066,15 @@ EXPORT_SYMBOL(nand_lock); * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { chip->read_buf(mtd, buf, mtd->writesize); - if (oob_required) - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); return 0; } @@ -1085,14 +1083,13 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * We need a special oob layout and handling even when OOB isn't used. */ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, - int oob_required, int page) + struct nand_chip *chip, + uint8_t *buf, int page) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1129,11 +1126,10 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read */ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1142,9 +1138,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; - unsigned int max_bitflips = 0; - chip->ecc.read_page_raw(mtd, chip, buf, 1, page); + chip->ecc.read_page_raw(mtd, chip, buf, page); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(mtd, p, &ecc_calc[i]); @@ -1159,14 +1154,12 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1187,7 +1180,6 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, int datafrag_len, eccfrag_len, aligned_len, aligned_pos; int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; int index = 0; - unsigned int max_bitflips = 0; /* Column address within the page aligned to ECC size (256bytes) */ start_step = data_offs / chip->ecc.size; @@ -1252,14 +1244,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1267,13 +1257,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Not for syndrome calculating ECC controllers which need a special oob layout. */ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1282,7 +1271,6 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; - unsigned int max_bitflips = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_READ); @@ -1301,14 +1289,12 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1316,7 +1302,6 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Hardware ECC for large page chips, require OOB to be read first. For this @@ -1326,7 +1311,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * the data area, by overwriting the NAND manufacturer bad block markings. */ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, int page) + struct nand_chip *chip, uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1335,7 +1320,6 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; uint8_t *ecc_calc = chip->buffers->ecccalc; - unsigned int max_bitflips = 0; /* Read the OOB area first */ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); @@ -1353,14 +1337,12 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, chip->ecc.calculate(mtd, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1368,21 +1350,19 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *oob = chip->oob_poi; - unsigned int max_bitflips = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; @@ -1399,12 +1379,10 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, oob, eccbytes); stat = chip->ecc.correct(mtd, p, oob, NULL); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } oob += eccbytes; @@ -1419,7 +1397,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, if (i) chip->read_buf(mtd, oob, i); - return max_bitflips; + return 0; } /** @@ -1481,9 +1459,11 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - int chipnr, page, realpage, col, bytes, aligned, oob_required; + int chipnr, page, realpage, col, bytes, aligned; struct nand_chip *chip = mtd->priv; struct mtd_ecc_stats stats; + int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; + int sndcmd = 1; int ret = 0; uint32_t readlen = ops->len; uint32_t oobreadlen = ops->ooblen; @@ -1491,7 +1471,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, mtd->oobavail : mtd->oobsize; uint8_t *bufpoi, *oob, *buf; - unsigned int max_bitflips = 0; stats = mtd->ecc_stats; @@ -1505,7 +1484,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, buf = ops->datbuf; oob = ops->oobbuf; - oob_required = oob ? 1 : 0; while (1) { bytes = min(mtd->writesize - col, readlen); @@ -1515,22 +1493,21 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, if (realpage != chip->pagebuf || oob) { bufpoi = aligned ? buf : chip->buffers->databuf; - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + if (likely(sndcmd)) { + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + sndcmd = 0; + } - /* - * Now read the page into the buffer. Absent an error, - * the read methods return max bitflips per ecc step. - */ + /* Now read the page into the buffer */ if (unlikely(ops->mode == MTD_OPS_RAW)) - ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, - oob_required, - page); + ret = chip->ecc.read_page_raw(mtd, chip, + bufpoi, page); else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); else ret = chip->ecc.read_page(mtd, chip, bufpoi, - oob_required, page); + page); if (ret < 0) { if (!aligned) /* Invalidate page cache */ @@ -1538,25 +1515,22 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, break; } - max_bitflips = max_t(unsigned int, max_bitflips, ret); - /* Transfer not aligned data */ if (!aligned) { if (!NAND_SUBPAGE_READ(chip) && !oob && !(mtd->ecc_stats.failed - stats.failed) && - (ops->mode != MTD_OPS_RAW)) { + (ops->mode != MTD_OPS_RAW)) chip->pagebuf = realpage; - chip->pagebuf_bitflips = ret; - } else { + else /* Invalidate page cache */ chip->pagebuf = -1; - } memcpy(buf, chip->buffers->databuf + col, bytes); } buf += bytes; if (unlikely(oob)) { + int toread = min(oobreadlen, max_oobsize); if (toread) { @@ -1567,7 +1541,13 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } if (!(chip->options & NAND_NO_READRDY)) { - /* Apply delay or wait for ready/busy pin */ + /* + * Apply delay or wait for ready/busy pin. Do + * this before the AUTOINCR check, so no + * problems arise if a chip which does auto + * increment is marked as NOAUTOINCR by the + * board driver. + */ if (!chip->dev_ready) udelay(chip->chip_delay); else @@ -1576,8 +1556,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } else { memcpy(buf, chip->buffers->databuf + col, bytes); buf += bytes; - max_bitflips = max_t(unsigned int, max_bitflips, - chip->pagebuf_bitflips); } readlen -= bytes; @@ -1597,19 +1575,26 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, -1); chip->select_chip(mtd, chipnr); } + + /* + * Check, if the chip supports auto page increment or if we + * have hit a block boundary. + */ + if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) + sndcmd = 1; } ops->retlen = ops->len - (size_t) readlen; if (oob) ops->oobretlen = ops->ooblen - oobreadlen; - if (ret < 0) + if (ret) return ret; if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; - return max_bitflips; + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** @@ -1645,13 +1630,17 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to read + * @sndcmd: flag whether to issue read command or not */ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + if (sndcmd) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; + } chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - return 0; + return sndcmd; } /** @@ -1660,9 +1649,10 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to read + * @sndcmd: flag whether to issue read command or not */ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { uint8_t *buf = chip->oob_poi; int length = mtd->oobsize; @@ -1689,7 +1679,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, if (length > 0) chip->read_buf(mtd, bufpoi, length); - return 0; + return 1; } /** @@ -1785,13 +1775,13 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - int page, realpage, chipnr; + int page, realpage, chipnr, sndcmd = 1; struct nand_chip *chip = mtd->priv; struct mtd_ecc_stats stats; + int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; int readlen = ops->ooblen; int len; uint8_t *buf = ops->oobbuf; - int ret = 0; pr_debug("%s: from = 0x%08Lx, len = %i\n", __func__, (unsigned long long)from, readlen); @@ -1827,18 +1817,20 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, while (1) { if (ops->mode == MTD_OPS_RAW) - ret = chip->ecc.read_oob_raw(mtd, chip, page); + sndcmd = chip->ecc.read_oob_raw(mtd, chip, page, sndcmd); else - ret = chip->ecc.read_oob(mtd, chip, page); - - if (ret < 0) - break; + sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); len = min(len, readlen); buf = nand_transfer_oob(chip, buf, ops, len); if (!(chip->options & NAND_NO_READRDY)) { - /* Apply delay or wait for ready/busy pin */ + /* + * Apply delay or wait for ready/busy pin. Do this + * before the AUTOINCR check, so no problems arise if a + * chip which does auto increment is marked as + * NOAUTOINCR by the board driver. + */ if (!chip->dev_ready) udelay(chip->chip_delay); else @@ -1859,12 +1851,16 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, -1); chip->select_chip(mtd, chipnr); } - } - ops->oobretlen = ops->ooblen - readlen; + /* + * Check, if the chip supports auto page increment or if we + * have hit a block boundary. + */ + if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) + sndcmd = 1; + } - if (ret < 0) - return ret; + ops->oobretlen = ops->ooblen; if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; @@ -1923,16 +1919,14 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { chip->write_buf(mtd, buf, mtd->writesize); - if (oob_required) - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); } /** @@ -1940,13 +1934,12 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB * * We need a special oob layout and handling even when ECC isn't checked. */ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1980,10 +1973,9 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB */ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1999,7 +1991,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; i < chip->ecc.total; i++) chip->oob_poi[eccpos[i]] = ecc_calc[i]; - chip->ecc.write_page_raw(mtd, chip, buf, 1); + chip->ecc.write_page_raw(mtd, chip, buf); } /** @@ -2007,10 +1999,9 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB */ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -2036,14 +2027,12 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB * * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ static void nand_write_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -2082,23 +2071,21 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, * @mtd: MTD device structure * @chip: NAND chip descriptor * @buf: the data to write - * @oob_required: must write chip->oob_poi to OOB * @page: page number to write * @cached: cached programming * @raw: use _raw version of write_page */ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page, - int cached, int raw) + const uint8_t *buf, int page, int cached, int raw) { int status; chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (unlikely(raw)) - chip->ecc.write_page_raw(mtd, chip, buf, oob_required); + chip->ecc.write_page_raw(mtd, chip, buf); else - chip->ecc.write_page(mtd, chip, buf, oob_required); + chip->ecc.write_page(mtd, chip, buf); /* * Cached progamming disabled for now. Not sure if it's worth the @@ -2131,9 +2118,6 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, if (chip->verify_buf(mtd, buf, mtd->writesize)) return -EIO; - - /* Make sure the next page prog is preceded by a status read */ - chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); #endif return 0; } @@ -2218,7 +2202,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, uint8_t *oob = ops->oobbuf; uint8_t *buf = ops->datbuf; int ret, subpage; - int oob_required = oob ? 1 : 0; ops->retlen = 0; if (!writelen) @@ -2281,8 +2264,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, memset(chip->oob_poi, 0xff, mtd->oobsize); } - ret = chip->write_page(mtd, chip, wbuf, oob_required, page, - cached, (ops->mode == MTD_OPS_RAW)); + ret = chip->write_page(mtd, chip, wbuf, page, cached, + (ops->mode == MTD_OPS_RAW)); if (ret) break; @@ -2915,7 +2898,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, *busw = NAND_BUSWIDTH_16; chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK; + chip->options |= (NAND_NO_READRDY | + NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; pr_info("ONFI flash detected\n"); return 1; @@ -3092,6 +3076,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; ident_done: + /* + * Set chip as a default. Board drivers can override it, if necessary. + */ + chip->options |= NAND_NO_AUTOINCR; + /* Try to identify manufacturer */ for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { if (nand_manuf_ids[maf_idx].id == *maf_id) @@ -3165,11 +3154,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (mtd->writesize > 512 && chip->cmdfunc == nand_command) chip->cmdfunc = nand_command_lp; - pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," - " page size: %d, OOB size: %d\n", - *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, - chip->onfi_version ? chip->onfi_params.model : type->name, - mtd->writesize, mtd->oobsize); + pr_info("NAND device: Manufacturer ID:" + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, + nand_manuf_ids[maf_idx].name, + chip->onfi_version ? chip->onfi_params.model : type->name); return type; } @@ -3341,13 +3329,8 @@ int nand_scan_tail(struct mtd_info *mtd) if (!chip->ecc.write_oob) chip->ecc.write_oob = nand_write_oob_syndrome; - if (mtd->writesize >= chip->ecc.size) { - if (!chip->ecc.strength) { - pr_warn("Driver must set ecc.strength when using hardware ECC\n"); - BUG(); - } + if (mtd->writesize >= chip->ecc.size) break; - } pr_warn("%d byte HW ECC not possible on " "%d byte page size, fallback to SW ECC\n", chip->ecc.size, mtd->writesize); @@ -3402,7 +3385,7 @@ int nand_scan_tail(struct mtd_info *mtd) BUG(); } chip->ecc.strength = - chip->ecc.bytes * 8 / fls(8 * chip->ecc.size); + chip->ecc.bytes*8 / fls(8*chip->ecc.size); break; case NAND_ECC_NONE: @@ -3500,7 +3483,7 @@ int nand_scan_tail(struct mtd_info *mtd) /* propagate ecc info to mtd_info */ mtd->ecclayout = chip->ecc.layout; - mtd->ecc_strength = chip->ecc.strength; + mtd->ecc_strength = chip->ecc.strength * chip->ecc.steps; /* Check, if we should skip the bad block table scan */ if (chip->options & NAND_SKIP_BBTSCAN) diff --git a/trunk/drivers/mtd/nand/nand_bbt.c b/trunk/drivers/mtd/nand/nand_bbt.c index 30d1319ff065..20a112f591fe 100644 --- a/trunk/drivers/mtd/nand/nand_bbt.c +++ b/trunk/drivers/mtd/nand/nand_bbt.c @@ -324,7 +324,6 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, buf += mtd->oobsize + mtd->writesize; len -= mtd->writesize; - offs += mtd->writesize; } return 0; } diff --git a/trunk/drivers/mtd/nand/nand_ids.c b/trunk/drivers/mtd/nand/nand_ids.c index 621b70b7a159..af4fe8ca7b5e 100644 --- a/trunk/drivers/mtd/nand/nand_ids.c +++ b/trunk/drivers/mtd/nand/nand_ids.c @@ -70,7 +70,7 @@ struct nand_flash_dev nand_flash_ids[] = { * These are the new chips with large page size. The pagesize and the * erasesize is determined from the extended id bytes */ -#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY) +#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR) #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) /* 512 Megabit */ @@ -157,7 +157,9 @@ struct nand_flash_dev nand_flash_ids[] = { * writes possible, but not implemented now */ {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, - NAND_IS_AND | NAND_NO_READRDY | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, + NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | + BBT_AUTO_REFRESH + }, {NULL,} }; diff --git a/trunk/drivers/mtd/nand/nandsim.c b/trunk/drivers/mtd/nand/nandsim.c index 6cc8fbfabb8e..261f478f8cc3 100644 --- a/trunk/drivers/mtd/nand/nandsim.c +++ b/trunk/drivers/mtd/nand/nandsim.c @@ -268,6 +268,7 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ #define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */ +#define OPT_AUTOINCR 0x00000020 /* page number auto incrementation is possible */ #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ @@ -593,7 +594,7 @@ static int init_nandsim(struct mtd_info *mtd) ns->options |= OPT_PAGE256; } else if (ns->geom.pgsz == 512) { - ns->options |= OPT_PAGE512; + ns->options |= (OPT_PAGE512 | OPT_AUTOINCR); if (ns->busw == 8) ns->options |= OPT_PAGE512_8BIT; } else if (ns->geom.pgsz == 2048) { @@ -662,6 +663,8 @@ static int init_nandsim(struct mtd_info *mtd) for (i = 0; nand_flash_ids[i].name != NULL; i++) { if (second_id_byte != nand_flash_ids[i].id) continue; + if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR)) + ns->options |= OPT_AUTOINCR; } if (ns->busw == 16) @@ -1933,8 +1936,20 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd) if (ns->regs.count == ns->regs.num) { NS_DBG("read_byte: all bytes were read\n"); - if (NS_STATE(ns->nxstate) == STATE_READY) + /* + * The OPT_AUTOINCR allows to read next consecutive pages without + * new read operation cycle. + */ + if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { + ns->regs.count = 0; + if (ns->regs.row + 1 < ns->geom.pgnum) + ns->regs.row += 1; + NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row); + do_state_action(ns, ACTION_CPY); + } + else if (NS_STATE(ns->nxstate) == STATE_READY) switch_state(ns); + } return outb; @@ -2188,7 +2203,14 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) ns->regs.count += len; if (ns->regs.count == ns->regs.num) { - if (NS_STATE(ns->nxstate) == STATE_READY) + if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { + ns->regs.count = 0; + if (ns->regs.row + 1 < ns->geom.pgnum) + ns->regs.row += 1; + NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row); + do_state_action(ns, ACTION_CPY); + } + else if (NS_STATE(ns->nxstate) == STATE_READY) switch_state(ns); } diff --git a/trunk/drivers/mtd/nand/omap2.c b/trunk/drivers/mtd/nand/omap2.c index d7f681d0c9b9..c2b0bba9d8b3 100644 --- a/trunk/drivers/mtd/nand/omap2.c +++ b/trunk/drivers/mtd/nand/omap2.c @@ -21,10 +21,6 @@ #include #include -#ifdef CONFIG_MTD_NAND_OMAP_BCH -#include -#endif - #include #include #include @@ -131,11 +127,6 @@ struct omap_nand_info { } iomode; u_char *buf; int buf_len; - -#ifdef CONFIG_MTD_NAND_OMAP_BCH - struct bch_control *bch; - struct nand_ecclayout ecclayout; -#endif }; /** @@ -411,7 +402,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); if (ret) /* PFPW engine is busy, use cpu copy method */ - goto out_copy_unmap; + goto out_copy; init_completion(&info->comp); @@ -430,8 +421,6 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); return 0; -out_copy_unmap: - dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); out_copy: if (info->nand.options & NAND_BUSWIDTH_16) is_write == 0 ? omap_read_buf16(mtd, (u_char *) addr, len) @@ -890,7 +879,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); unsigned long timeo = jiffies; - int status, state = this->state; + int status = NAND_STATUS_FAIL, state = this->state; if (state == FL_ERASING) timeo += (HZ * 400) / 1000; @@ -905,8 +894,6 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) break; cond_resched(); } - - status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA); return status; } @@ -938,226 +925,6 @@ static int omap_dev_ready(struct mtd_info *mtd) return 1; } -#ifdef CONFIG_MTD_NAND_OMAP_BCH - -/** - * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction - * @mtd: MTD device structure - * @mode: Read/Write mode - */ -static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) -{ - int nerrors; - unsigned int dev_width; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - struct nand_chip *chip = mtd->priv; - - nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4; - dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; - /* - * Program GPMC to perform correction on one 512-byte sector at a time. - * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and - * gives a slight (5%) performance gain (but requires additional code). - */ - (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors); -} - -/** - * omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes - * @mtd: MTD device structure - * @dat: The pointer to data on which ecc is computed - * @ecc_code: The ecc_code buffer - */ -static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code); -} - -/** - * omap3_calculate_ecc_bch8 - Generate 13 bytes of ECC bytes - * @mtd: MTD device structure - * @dat: The pointer to data on which ecc is computed - * @ecc_code: The ecc_code buffer - */ -static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code); -} - -/** - * omap3_correct_data_bch - Decode received data and correct errors - * @mtd: MTD device structure - * @data: page data - * @read_ecc: ecc read from nand flash - * @calc_ecc: ecc read from HW ECC registers - */ -static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data, - u_char *read_ecc, u_char *calc_ecc) -{ - int i, count; - /* cannot correct more than 8 errors */ - unsigned int errloc[8]; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - - count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL, - errloc); - if (count > 0) { - /* correct errors */ - for (i = 0; i < count; i++) { - /* correct data only, not ecc bytes */ - if (errloc[i] < 8*512) - data[errloc[i]/8] ^= 1 << (errloc[i] & 7); - pr_debug("corrected bitflip %u\n", errloc[i]); - } - } else if (count < 0) { - pr_err("ecc unrecoverable error\n"); - } - return count; -} - -/** - * omap3_free_bch - Release BCH ecc resources - * @mtd: MTD device structure - */ -static void omap3_free_bch(struct mtd_info *mtd) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - if (info->bch) { - free_bch(info->bch); - info->bch = NULL; - } -} - -/** - * omap3_init_bch - Initialize BCH ECC - * @mtd: MTD device structure - * @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW) - */ -static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) -{ - int ret, max_errors; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); -#ifdef CONFIG_MTD_NAND_OMAP_BCH8 - const int hw_errors = 8; -#else - const int hw_errors = 4; -#endif - info->bch = NULL; - - max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ? 8 : 4; - if (max_errors != hw_errors) { - pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported", - max_errors, hw_errors); - goto fail; - } - - /* initialize GPMC BCH engine */ - ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors); - if (ret) - goto fail; - - /* software bch library is only used to detect and locate errors */ - info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */); - if (!info->bch) - goto fail; - - info->nand.ecc.size = 512; - info->nand.ecc.hwctl = omap3_enable_hwecc_bch; - info->nand.ecc.correct = omap3_correct_data_bch; - info->nand.ecc.mode = NAND_ECC_HW; - - /* - * The number of corrected errors in an ecc block that will trigger - * block scrubbing defaults to the ecc strength (4 or 8). - * Set mtd->bitflip_threshold here to define a custom threshold. - */ - - if (max_errors == 8) { - info->nand.ecc.strength = 8; - info->nand.ecc.bytes = 13; - info->nand.ecc.calculate = omap3_calculate_ecc_bch8; - } else { - info->nand.ecc.strength = 4; - info->nand.ecc.bytes = 7; - info->nand.ecc.calculate = omap3_calculate_ecc_bch4; - } - - pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors); - return 0; -fail: - omap3_free_bch(mtd); - return -1; -} - -/** - * omap3_init_bch_tail - Build an oob layout for BCH ECC correction. - * @mtd: MTD device structure - */ -static int omap3_init_bch_tail(struct mtd_info *mtd) -{ - int i, steps; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - struct nand_ecclayout *layout = &info->ecclayout; - - /* build oob layout */ - steps = mtd->writesize/info->nand.ecc.size; - layout->eccbytes = steps*info->nand.ecc.bytes; - - /* do not bother creating special oob layouts for small page devices */ - if (mtd->oobsize < 64) { - pr_err("BCH ecc is not supported on small page devices\n"); - goto fail; - } - - /* reserve 2 bytes for bad block marker */ - if (layout->eccbytes+2 > mtd->oobsize) { - pr_err("no oob layout available for oobsize %d eccbytes %u\n", - mtd->oobsize, layout->eccbytes); - goto fail; - } - - /* put ecc bytes at oob tail */ - for (i = 0; i < layout->eccbytes; i++) - layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i; - - layout->oobfree[0].offset = 2; - layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; - info->nand.ecc.layout = layout; - - if (!(info->nand.options & NAND_BUSWIDTH_16)) - info->nand.badblock_pattern = &bb_descrip_flashbased; - return 0; -fail: - omap3_free_bch(mtd); - return -1; -} - -#else -static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) -{ - pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n"); - return -1; -} -static int omap3_init_bch_tail(struct mtd_info *mtd) -{ - return -1; -} -static void omap3_free_bch(struct mtd_info *mtd) -{ -} -#endif /* CONFIG_MTD_NAND_OMAP_BCH */ - static int __devinit omap_nand_probe(struct platform_device *pdev) { struct omap_nand_info *info; @@ -1296,13 +1063,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.ecc.hwctl = omap_enable_hwecc; info->nand.ecc.correct = omap_correct_data; info->nand.ecc.mode = NAND_ECC_HW; - } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { - err = omap3_init_bch(&info->mtd, pdata->ecc_opt); - if (err) { - err = -EINVAL; - goto out_release_mem_region; - } } /* DIP switches on some boards change between 8 and 16 bit @@ -1334,14 +1094,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) (offset + omap_oobinfo.eccbytes); info->nand.ecc.layout = &omap_oobinfo; - } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { - /* build OOB layout for BCH ECC correction */ - err = omap3_init_bch_tail(&info->mtd); - if (err) { - err = -EINVAL; - goto out_release_mem_region; - } } /* second phase scan */ @@ -1370,7 +1122,6 @@ static int omap_nand_remove(struct platform_device *pdev) struct mtd_info *mtd = platform_get_drvdata(pdev); struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - omap3_free_bch(&info->mtd); platform_set_drvdata(pdev, NULL); if (info->dma_ch != -1) diff --git a/trunk/drivers/mtd/nand/pasemi_nand.c b/trunk/drivers/mtd/nand/pasemi_nand.c index 1440e51cedcc..974dbf8251c9 100644 --- a/trunk/drivers/mtd/nand/pasemi_nand.c +++ b/trunk/drivers/mtd/nand/pasemi_nand.c @@ -155,6 +155,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) chip->ecc.mode = NAND_ECC_SOFT; /* Enable the following for a flash based bad block table */ + chip->options = NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; /* Scan to find existence of the device */ diff --git a/trunk/drivers/mtd/nand/plat_nand.c b/trunk/drivers/mtd/nand/plat_nand.c index 1bcb52040422..6404e6e81b10 100644 --- a/trunk/drivers/mtd/nand/plat_nand.c +++ b/trunk/drivers/mtd/nand/plat_nand.c @@ -23,18 +23,14 @@ struct plat_nand_data { void __iomem *io_base; }; -static const char *part_probe_types[] = { "cmdlinepart", NULL }; - /* * Probe for the NAND device. */ static int __devinit plat_nand_probe(struct platform_device *pdev) { struct platform_nand_data *pdata = pdev->dev.platform_data; - struct mtd_part_parser_data ppdata; struct plat_nand_data *data; struct resource *res; - const char **part_types; int err = 0; if (pdata->chip.nr_chips < 1) { @@ -79,7 +75,6 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) data->chip.select_chip = pdata->ctrl.select_chip; data->chip.write_buf = pdata->ctrl.write_buf; data->chip.read_buf = pdata->ctrl.read_buf; - data->chip.read_byte = pdata->ctrl.read_byte; data->chip.chip_delay = pdata->chip.chip_delay; data->chip.options |= pdata->chip.options; data->chip.bbt_options |= pdata->chip.bbt_options; @@ -103,10 +98,8 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) goto out; } - part_types = pdata->chip.part_probe_types ? : part_probe_types; - - ppdata.of_node = pdev->dev.of_node; - err = mtd_device_parse_register(&data->mtd, part_types, &ppdata, + err = mtd_device_parse_register(&data->mtd, + pdata->chip.part_probe_types, NULL, pdata->chip.partitions, pdata->chip.nr_partitions); @@ -147,19 +140,12 @@ static int __devexit plat_nand_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id plat_nand_match[] = { - { .compatible = "gen_nand" }, - {}, -}; -MODULE_DEVICE_TABLE(of, plat_nand_match); - static struct platform_driver plat_nand_driver = { - .probe = plat_nand_probe, - .remove = __devexit_p(plat_nand_remove), - .driver = { - .name = "gen_nand", - .owner = THIS_MODULE, - .of_match_table = plat_nand_match, + .probe = plat_nand_probe, + .remove = __devexit_p(plat_nand_remove), + .driver = { + .name = "gen_nand", + .owner = THIS_MODULE, }, }; diff --git a/trunk/drivers/mtd/nand/pxa3xx_nand.c b/trunk/drivers/mtd/nand/pxa3xx_nand.c index 252aaefcacfa..def50caa6f84 100644 --- a/trunk/drivers/mtd/nand/pxa3xx_nand.c +++ b/trunk/drivers/mtd/nand/pxa3xx_nand.c @@ -682,15 +682,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, } static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { chip->write_buf(mtd, buf, mtd->writesize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); } static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, - int page) + struct nand_chip *chip, uint8_t *buf, int page) { struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_info *info = host->info_data; @@ -1005,6 +1004,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) chip->ecc.size = host->page_size; chip->ecc.strength = 1; + chip->options = NAND_NO_AUTOINCR; chip->options |= NAND_NO_READRDY; if (host->reg_ndcr & NDCR_DWIDTH_M) chip->options |= NAND_BUSWIDTH_16; diff --git a/trunk/drivers/mtd/nand/r852.c b/trunk/drivers/mtd/nand/r852.c index 8cb627751c9c..c2040187c813 100644 --- a/trunk/drivers/mtd/nand/r852.c +++ b/trunk/drivers/mtd/nand/r852.c @@ -539,11 +539,14 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, * nand_read_oob_syndrome assumes we can send column address - we can't */ static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + if (sndcmd) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; + } chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - return 0; + return sndcmd; } /* @@ -1101,7 +1104,18 @@ static struct pci_driver r852_pci_driver = { .driver.pm = &r852_pm_ops, }; -module_pci_driver(r852_pci_driver); +static __init int r852_module_init(void) +{ + return pci_register_driver(&r852_pci_driver); +} + +static void __exit r852_module_exit(void) +{ + pci_unregister_driver(&r852_pci_driver); +} + +module_init(r852_module_init); +module_exit(r852_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Maxim Levitsky "); diff --git a/trunk/drivers/mtd/nand/sh_flctl.c b/trunk/drivers/mtd/nand/sh_flctl.c index aa9b8a5e0b8f..e9b2b260de3a 100644 --- a/trunk/drivers/mtd/nand/sh_flctl.c +++ b/trunk/drivers/mtd/nand/sh_flctl.c @@ -344,7 +344,7 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va } static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -359,14 +359,14 @@ static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, if (flctl->hwecc_cant_correct[i]) mtd->ecc_stats.failed++; else - mtd->ecc_stats.corrected += 0; /* FIXME */ + mtd->ecc_stats.corrected += 0; } return 0; } static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -881,6 +881,8 @@ static int __devinit flctl_probe(struct platform_device *pdev) flctl->hwecc = pdata->has_hwecc; flctl->holden = pdata->use_holden; + nand->options = NAND_NO_AUTOINCR; + /* Set address of hardware control function */ /* 20 us command delay time */ nand->chip_delay = 20; diff --git a/trunk/drivers/mtd/nand/sm_common.c b/trunk/drivers/mtd/nand/sm_common.c index 082bcdcd6bcf..774c3c266713 100644 --- a/trunk/drivers/mtd/nand/sm_common.c +++ b/trunk/drivers/mtd/nand/sm_common.c @@ -94,16 +94,17 @@ static struct nand_flash_dev nand_smartmedia_flash_ids[] = { {NULL,} }; +#define XD_TYPEM (NAND_NO_AUTOINCR | NAND_BROKEN_XD) static struct nand_flash_dev nand_xd_flash_ids[] = { {"xD 16MiB 3,3V", 0x73, 512, 16, 0x4000, 0}, {"xD 32MiB 3,3V", 0x75, 512, 32, 0x4000, 0}, {"xD 64MiB 3,3V", 0x76, 512, 64, 0x4000, 0}, {"xD 128MiB 3,3V", 0x79, 512, 128, 0x4000, 0}, - {"xD 256MiB 3,3V", 0x71, 512, 256, 0x4000, NAND_BROKEN_XD}, - {"xD 512MiB 3,3V", 0xdc, 512, 512, 0x4000, NAND_BROKEN_XD}, - {"xD 1GiB 3,3V", 0xd3, 512, 1024, 0x4000, NAND_BROKEN_XD}, - {"xD 2GiB 3,3V", 0xd5, 512, 2048, 0x4000, NAND_BROKEN_XD}, + {"xD 256MiB 3,3V", 0x71, 512, 256, 0x4000, XD_TYPEM}, + {"xD 512MiB 3,3V", 0xdc, 512, 512, 0x4000, XD_TYPEM}, + {"xD 1GiB 3,3V", 0xd3, 512, 1024, 0x4000, XD_TYPEM}, + {"xD 2GiB 3,3V", 0xd5, 512, 2048, 0x4000, XD_TYPEM}, {NULL,} }; diff --git a/trunk/drivers/mtd/onenand/onenand_base.c b/trunk/drivers/mtd/onenand/onenand_base.c index 7153e0d27101..b3ce12ef359e 100644 --- a/trunk/drivers/mtd/onenand/onenand_base.c +++ b/trunk/drivers/mtd/onenand/onenand_base.c @@ -1201,8 +1201,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; - /* return max bitflips per ecc step; ONENANDs correct 1 bit only */ - return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0; + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** @@ -1334,8 +1333,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; - /* return max bitflips per ecc step; ONENANDs correct 1 bit only */ - return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0; + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** diff --git a/trunk/drivers/pinctrl/pinctrl-nomadik.c b/trunk/drivers/pinctrl/pinctrl-nomadik.c index b26395d16347..b8e01c3eaa95 100644 --- a/trunk/drivers/pinctrl/pinctrl-nomadik.c +++ b/trunk/drivers/pinctrl/pinctrl-nomadik.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -1689,34 +1688,18 @@ static struct pinctrl_desc nmk_pinctrl_desc = { .owner = THIS_MODULE, }; -static const struct of_device_id nmk_pinctrl_match[] = { - { - .compatible = "stericsson,nmk_pinctrl", - .data = (void *)PINCTRL_NMK_DB8500, - }, - {}, -}; - static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) { const struct platform_device_id *platid = platform_get_device_id(pdev); - struct device_node *np = pdev->dev.of_node; struct nmk_pinctrl *npct; - unsigned int version = 0; int i; npct = devm_kzalloc(&pdev->dev, sizeof(*npct), GFP_KERNEL); if (!npct) return -ENOMEM; - if (platid) - version = platid->driver_data; - else if (np) - version = (unsigned int) - of_match_device(nmk_pinctrl_match, &pdev->dev)->data; - /* Poke in other ASIC variants here */ - if (version == PINCTRL_NMK_DB8500) + if (platid->driver_data == PINCTRL_NMK_DB8500) nmk_pinctrl_db8500_init(&npct->soc); /* @@ -1775,7 +1758,6 @@ static struct platform_driver nmk_pinctrl_driver = { .driver = { .owner = THIS_MODULE, .name = "pinctrl-nomadik", - .of_match_table = nmk_pinctrl_match, }, .probe = nmk_pinctrl_probe, .id_table = nmk_pinctrl_id, diff --git a/trunk/drivers/platform/x86/acer-wmi.c b/trunk/drivers/platform/x86/acer-wmi.c index ce875dc365e5..c1a3fd8e1243 100644 --- a/trunk/drivers/platform/x86/acer-wmi.c +++ b/trunk/drivers/platform/x86/acer-wmi.c @@ -523,30 +523,6 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"), }, }, - { - .callback = video_set_backlight_video_vendor, - .ident = "Acer Extensa 5235", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"), - }, - }, - { - .callback = video_set_backlight_video_vendor, - .ident = "Acer TravelMate 5760", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"), - }, - }, - { - .callback = video_set_backlight_video_vendor, - .ident = "Acer Aspire 5750", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), - }, - }, {} }; diff --git a/trunk/drivers/platform/x86/apple-gmux.c b/trunk/drivers/platform/x86/apple-gmux.c index 694a15a56230..8a582bdfdc76 100644 --- a/trunk/drivers/platform/x86/apple-gmux.c +++ b/trunk/drivers/platform/x86/apple-gmux.c @@ -87,9 +87,6 @@ static int gmux_update_status(struct backlight_device *bd) struct apple_gmux_data *gmux_data = bl_get_data(bd); u32 brightness = bd->props.brightness; - if (bd->props.state & BL_CORE_SUSPENDED) - return 0; - /* * Older gmux versions require writing out lower bytes first then * setting the upper byte to 0 to flush the values. Newer versions @@ -105,7 +102,6 @@ static int gmux_update_status(struct backlight_device *bd) } static const struct backlight_ops gmux_bl_ops = { - .options = BL_CORE_SUSPENDRESUME, .get_brightness = gmux_get_brightness, .update_status = gmux_update_status, }; diff --git a/trunk/drivers/platform/x86/dell-laptop.c b/trunk/drivers/platform/x86/dell-laptop.c index 5f78aac9b163..e6c08ee8d46c 100644 --- a/trunk/drivers/platform/x86/dell-laptop.c +++ b/trunk/drivers/platform/x86/dell-laptop.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -89,8 +90,11 @@ static struct platform_driver platform_driver = { static struct platform_device *platform_device; static struct backlight_device *dell_backlight_device; +static struct rfkill *wifi_rfkill; +static struct rfkill *bluetooth_rfkill; +static struct rfkill *wwan_rfkill; -static const struct dmi_system_id dell_device_table[] __initconst = { +static const struct dmi_system_id __initdata dell_device_table[] = { { .ident = "Dell laptop", .matches = { @@ -115,94 +119,96 @@ static const struct dmi_system_id dell_device_table[] __initconst = { }; MODULE_DEVICE_TABLE(dmi, dell_device_table); -static struct dmi_system_id __devinitdata dell_quirks[] = { +static struct dmi_system_id __devinitdata dell_blacklist[] = { + /* Supported by compal-laptop */ { - .callback = dmi_matched, - .ident = "Dell Vostro V130", + .ident = "Dell Mini 9", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Vostro V131", + .ident = "Dell Mini 10", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Vostro 3350", + .ident = "Dell Mini 10v", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Vostro 3555", + .ident = "Dell Mini 1012", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Inspiron N311z", + .ident = "Dell Inspiron 11z", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), + }, + }, + { + .ident = "Dell Mini 12", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), }, - .driver_data = &quirk_dell_vostro_v130, }, + {} +}; + +static struct dmi_system_id __devinitdata dell_quirks[] = { { .callback = dmi_matched, - .ident = "Dell Inspiron M5110", + .ident = "Dell Vostro V130", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3360", + .ident = "Dell Vostro V131", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3360"), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3460", + .ident = "Dell Vostro 3555", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3460"), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3560", + .ident = "Dell Inspiron N311z", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3560"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3450", + .ident = "Dell Inspiron M5110", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Dell System Vostro 3450"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -299,6 +305,94 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, return buffer; } +/* Derived from information in DellWirelessCtl.cpp: + Class 17, select 11 is radio control. It returns an array of 32-bit values. + + Input byte 0 = 0: Wireless information + + result[0]: return code + result[1]: + Bit 0: Hardware switch supported + Bit 1: Wifi locator supported + Bit 2: Wifi is supported + Bit 3: Bluetooth is supported + Bit 4: WWAN is supported + Bit 5: Wireless keyboard supported + Bits 6-7: Reserved + Bit 8: Wifi is installed + Bit 9: Bluetooth is installed + Bit 10: WWAN is installed + Bits 11-15: Reserved + Bit 16: Hardware switch is on + Bit 17: Wifi is blocked + Bit 18: Bluetooth is blocked + Bit 19: WWAN is blocked + Bits 20-31: Reserved + result[2]: NVRAM size in bytes + result[3]: NVRAM format version number + + Input byte 0 = 2: Wireless switch configuration + result[0]: return code + result[1]: + Bit 0: Wifi controlled by switch + Bit 1: Bluetooth controlled by switch + Bit 2: WWAN controlled by switch + Bits 3-6: Reserved + Bit 7: Wireless switch config locked + Bit 8: Wifi locator enabled + Bits 9-14: Reserved + Bit 15: Wifi locator setting locked + Bits 16-31: Reserved +*/ + +static int dell_rfkill_set(void *data, bool blocked) +{ + int disable = blocked ? 1 : 0; + unsigned long radio = (unsigned long)data; + int hwswitch_bit = (unsigned long)data - 1; + int ret = 0; + + get_buffer(); + dell_send_request(buffer, 17, 11); + + /* If the hardware switch controls this radio, and the hardware + switch is disabled, don't allow changing the software state */ + if ((hwswitch_state & BIT(hwswitch_bit)) && + !(buffer->output[1] & BIT(16))) { + ret = -EINVAL; + goto out; + } + + buffer->input[0] = (1 | (radio<<8) | (disable << 16)); + dell_send_request(buffer, 17, 11); + +out: + release_buffer(); + return ret; +} + +static void dell_rfkill_query(struct rfkill *rfkill, void *data) +{ + int status; + int bit = (unsigned long)data + 16; + int hwswitch_bit = (unsigned long)data - 1; + + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; + release_buffer(); + + rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); + + if (hwswitch_state & (BIT(hwswitch_bit))) + rfkill_set_hw_state(rfkill, !(status & BIT(16))); +} + +static const struct rfkill_ops dell_rfkill_ops = { + .set_block = dell_rfkill_set, + .query = dell_rfkill_query, +}; + static struct dentry *dell_laptop_dir; static int dell_debugfs_show(struct seq_file *s, void *data) @@ -368,6 +462,108 @@ static const struct file_operations dell_debugfs_fops = { .release = single_release, }; +static void dell_update_rfkill(struct work_struct *ignored) +{ + if (wifi_rfkill) + dell_rfkill_query(wifi_rfkill, (void *)1); + if (bluetooth_rfkill) + dell_rfkill_query(bluetooth_rfkill, (void *)2); + if (wwan_rfkill) + dell_rfkill_query(wwan_rfkill, (void *)3); +} +static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); + + +static int __init dell_setup_rfkill(void) +{ + int status; + int ret; + + if (dmi_check_system(dell_blacklist)) { + pr_info("Blacklisted hardware detected - not enabling rfkill\n"); + return 0; + } + + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + hwswitch_state = buffer->output[1]; + release_buffer(); + + if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { + wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, + RFKILL_TYPE_WLAN, + &dell_rfkill_ops, (void *) 1); + if (!wifi_rfkill) { + ret = -ENOMEM; + goto err_wifi; + } + ret = rfkill_register(wifi_rfkill); + if (ret) + goto err_wifi; + } + + if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { + bluetooth_rfkill = rfkill_alloc("dell-bluetooth", + &platform_device->dev, + RFKILL_TYPE_BLUETOOTH, + &dell_rfkill_ops, (void *) 2); + if (!bluetooth_rfkill) { + ret = -ENOMEM; + goto err_bluetooth; + } + ret = rfkill_register(bluetooth_rfkill); + if (ret) + goto err_bluetooth; + } + + if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { + wwan_rfkill = rfkill_alloc("dell-wwan", + &platform_device->dev, + RFKILL_TYPE_WWAN, + &dell_rfkill_ops, (void *) 3); + if (!wwan_rfkill) { + ret = -ENOMEM; + goto err_wwan; + } + ret = rfkill_register(wwan_rfkill); + if (ret) + goto err_wwan; + } + + return 0; +err_wwan: + rfkill_destroy(wwan_rfkill); + if (bluetooth_rfkill) + rfkill_unregister(bluetooth_rfkill); +err_bluetooth: + rfkill_destroy(bluetooth_rfkill); + if (wifi_rfkill) + rfkill_unregister(wifi_rfkill); +err_wifi: + rfkill_destroy(wifi_rfkill); + + return ret; +} + +static void dell_cleanup_rfkill(void) +{ + if (wifi_rfkill) { + rfkill_unregister(wifi_rfkill); + rfkill_destroy(wifi_rfkill); + } + if (bluetooth_rfkill) { + rfkill_unregister(bluetooth_rfkill); + rfkill_destroy(bluetooth_rfkill); + } + if (wwan_rfkill) { + rfkill_unregister(wwan_rfkill); + rfkill_destroy(wwan_rfkill); + } +} + static int dell_send_intensity(struct backlight_device *bd) { int ret = 0; @@ -459,6 +655,30 @@ static void touchpad_led_exit(void) led_classdev_unregister(&touchpad_led); } +static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, + struct serio *port) +{ + static bool extended; + + if (str & 0x20) + return false; + + if (unlikely(data == 0xe0)) { + extended = true; + return false; + } else if (unlikely(extended)) { + switch (data) { + case 0x8: + schedule_delayed_work(&dell_rfkill_work, + round_jiffies_relative(HZ)); + break; + } + extended = false; + } + + return false; +} + static int __init dell_init(void) { int max_intensity = 0; @@ -500,10 +720,26 @@ static int __init dell_init(void) goto fail_buffer; buffer = page_address(bufferpage); + ret = dell_setup_rfkill(); + + if (ret) { + pr_warn("Unable to setup rfkill\n"); + goto fail_rfkill; + } + + ret = i8042_install_filter(dell_laptop_i8042_filter); + if (ret) { + pr_warn("Unable to install key filter\n"); + goto fail_filter; + } + if (quirks && quirks->touchpad_led) touchpad_led_init(&platform_device->dev); dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); + if (dell_laptop_dir != NULL) + debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, + &dell_debugfs_fops); #ifdef CONFIG_ACPI /* In the event of an ACPI backlight being available, don't @@ -546,6 +782,11 @@ static int __init dell_init(void) return 0; fail_backlight: + i8042_remove_filter(dell_laptop_i8042_filter); + cancel_delayed_work_sync(&dell_rfkill_work); +fail_filter: + dell_cleanup_rfkill(); +fail_rfkill: free_page((unsigned long)bufferpage); fail_buffer: platform_device_del(platform_device); @@ -563,7 +804,10 @@ static void __exit dell_exit(void) debugfs_remove_recursive(dell_laptop_dir); if (quirks && quirks->touchpad_led) touchpad_led_exit(); + i8042_remove_filter(dell_laptop_i8042_filter); + cancel_delayed_work_sync(&dell_rfkill_work); backlight_device_unregister(dell_backlight_device); + dell_cleanup_rfkill(); if (platform_device) { platform_device_unregister(platform_device); platform_driver_unregister(&platform_driver); diff --git a/trunk/drivers/platform/x86/fujitsu-tablet.c b/trunk/drivers/platform/x86/fujitsu-tablet.c index da267eae8ba8..580d80a73c3a 100644 --- a/trunk/drivers/platform/x86/fujitsu-tablet.c +++ b/trunk/drivers/platform/x86/fujitsu-tablet.c @@ -16,8 +16,6 @@ * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -36,8 +34,7 @@ #define ACPI_FUJITSU_CLASS "fujitsu" #define INVERT_TABLET_MODE_BIT 0x01 -#define INVERT_DOCK_STATE_BIT 0x02 -#define FORCE_TABLET_MODE_IF_UNDOCK 0x04 +#define FORCE_TABLET_MODE_IF_UNDOCK 0x02 #define KEYMAP_LEN 16 @@ -164,8 +161,6 @@ static void fujitsu_send_state(void) state = fujitsu_read_register(0xdd); dock = state & 0x02; - if (fujitsu.config.quirks & INVERT_DOCK_STATE_BIT) - dock = !dock; if ((fujitsu.config.quirks & FORCE_TABLET_MODE_IF_UNDOCK) && (!dock)) { tablet_mode = 1; @@ -226,6 +221,9 @@ static int __devinit input_fujitsu_setup(struct device *parent, input_set_capability(idev, EV_SW, SW_DOCK); input_set_capability(idev, EV_SW, SW_TABLET_MODE); + input_set_capability(idev, EV_SW, SW_DOCK); + input_set_capability(idev, EV_SW, SW_TABLET_MODE); + error = input_register_device(idev); if (error) { input_free_device(idev); @@ -277,31 +275,25 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void __devinit fujitsu_dmi_common(const struct dmi_system_id *dmi) +static int __devinit fujitsu_dmi_default(const struct dmi_system_id *dmi) { - pr_info("%s\n", dmi->ident); + printk(KERN_INFO MODULENAME ": %s\n", dmi->ident); memcpy(fujitsu.config.keymap, dmi->driver_data, sizeof(fujitsu.config.keymap)); -} - -static int __devinit fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) -{ - fujitsu_dmi_common(dmi); - fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; return 1; } static int __devinit fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) { - fujitsu_dmi_common(dmi); + fujitsu_dmi_default(dmi); fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; - fujitsu.config.quirks |= INVERT_DOCK_STATE_BIT; + fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; return 1; } static struct dmi_system_id dmi_ids[] __initconst = { { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Fujitsu Siemens P/T Series", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), @@ -310,7 +302,7 @@ static struct dmi_system_id dmi_ids[] __initconst = { .driver_data = keymap_Lifebook_Tseries }, { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Fujitsu Lifebook T Series", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), @@ -328,7 +320,7 @@ static struct dmi_system_id dmi_ids[] __initconst = { .driver_data = keymap_Stylistic_Tseries }, { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Fujitsu LifeBook U810", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), @@ -355,7 +347,7 @@ static struct dmi_system_id dmi_ids[] __initconst = { .driver_data = keymap_Stylistic_ST5xxx }, { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Unknown (using defaults)", .matches = { DMI_MATCH(DMI_SYS_VENDOR, ""), @@ -481,6 +473,6 @@ module_exit(fujitsu_module_exit); MODULE_AUTHOR("Robert Gerlach "); MODULE_DESCRIPTION("Fujitsu tablet pc extras driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("2.5"); +MODULE_VERSION("2.4"); MODULE_DEVICE_TABLE(acpi, fujitsu_ids); diff --git a/trunk/drivers/platform/x86/hdaps.c b/trunk/drivers/platform/x86/hdaps.c index 24a3ae065f1b..7387f97a2941 100644 --- a/trunk/drivers/platform/x86/hdaps.c +++ b/trunk/drivers/platform/x86/hdaps.c @@ -2,7 +2,7 @@ * hdaps.c - driver for IBM's Hard Drive Active Protection System * * Copyright (C) 2005 Robert Love - * Copyright (C) 2005 Jesper Juhl + * Copyright (C) 2005 Jesper Juhl * * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads * starting with the R40, T41, and X40. It provides a basic two-axis diff --git a/trunk/drivers/platform/x86/hp-wmi.c b/trunk/drivers/platform/x86/hp-wmi.c index 387183a2d6dd..e2faa3cbb792 100644 --- a/trunk/drivers/platform/x86/hp-wmi.c +++ b/trunk/drivers/platform/x86/hp-wmi.c @@ -634,8 +634,6 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) RFKILL_TYPE_WLAN, &hp_wmi_rfkill_ops, (void *) HPWMI_WIFI); - if (!wifi_rfkill) - return -ENOMEM; rfkill_init_sw_state(wifi_rfkill, hp_wmi_get_sw_state(HPWMI_WIFI)); rfkill_set_hw_state(wifi_rfkill, @@ -650,10 +648,6 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) RFKILL_TYPE_BLUETOOTH, &hp_wmi_rfkill_ops, (void *) HPWMI_BLUETOOTH); - if (!bluetooth_rfkill) { - err = -ENOMEM; - goto register_wifi_error; - } rfkill_init_sw_state(bluetooth_rfkill, hp_wmi_get_sw_state(HPWMI_BLUETOOTH)); rfkill_set_hw_state(bluetooth_rfkill, @@ -668,10 +662,6 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) RFKILL_TYPE_WWAN, &hp_wmi_rfkill_ops, (void *) HPWMI_WWAN); - if (!wwan_rfkill) { - err = -ENOMEM; - goto register_bluetooth_error; - } rfkill_init_sw_state(wwan_rfkill, hp_wmi_get_sw_state(HPWMI_WWAN)); rfkill_set_hw_state(wwan_rfkill, diff --git a/trunk/drivers/platform/x86/ideapad-laptop.c b/trunk/drivers/platform/x86/ideapad-laptop.c index 4f20f8dd3d7c..ac902f7a9baa 100644 --- a/trunk/drivers/platform/x86/ideapad-laptop.c +++ b/trunk/drivers/platform/x86/ideapad-laptop.c @@ -194,6 +194,7 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data) /* * debugfs */ +#define DEBUGFS_EVENT_LEN (4096) static int debugfs_status_show(struct seq_file *s, void *data) { unsigned long value; @@ -314,7 +315,7 @@ static int __devinit ideapad_debugfs_init(struct ideapad_private *priv) node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL, &debugfs_status_fops); if (!node) { - pr_err("failed to create status in debugfs"); + pr_err("failed to create event in debugfs"); goto errout; } @@ -784,10 +785,6 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) case 9: ideapad_sync_rfk_state(priv); break; - case 13: - case 6: - ideapad_input_report(priv, vpc_bit); - break; case 4: ideapad_backlight_notify_brightness(priv); break; @@ -798,7 +795,7 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) ideapad_backlight_notify_power(priv); break; default: - pr_info("Unknown event: %lu\n", vpc_bit); + ideapad_input_report(priv, vpc_bit); } } } diff --git a/trunk/drivers/platform/x86/sony-laptop.c b/trunk/drivers/platform/x86/sony-laptop.c index 210d4ae547c2..8a51795aa02a 100644 --- a/trunk/drivers/platform/x86/sony-laptop.c +++ b/trunk/drivers/platform/x86/sony-laptop.c @@ -141,27 +141,6 @@ MODULE_PARM_DESC(kbd_backlight_timeout, "(default: 0)"); static void sony_nc_kbd_backlight_resume(void); -static int sony_nc_kbd_backlight_setup(struct platform_device *pd, - unsigned int handle); -static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); - -static int sony_nc_battery_care_setup(struct platform_device *pd, - unsigned int handle); -static void sony_nc_battery_care_cleanup(struct platform_device *pd); - -static int sony_nc_thermal_setup(struct platform_device *pd); -static void sony_nc_thermal_cleanup(struct platform_device *pd); -static void sony_nc_thermal_resume(void); - -static int sony_nc_lid_resume_setup(struct platform_device *pd); -static void sony_nc_lid_resume_cleanup(struct platform_device *pd); - -static int sony_nc_highspeed_charging_setup(struct platform_device *pd); -static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); - -static int sony_nc_touchpad_setup(struct platform_device *pd, - unsigned int handle); -static void sony_nc_touchpad_cleanup(struct platform_device *pd); enum sony_nc_rfkill { SONY_WIFI, @@ -174,9 +153,6 @@ enum sony_nc_rfkill { static int sony_rfkill_handle; static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; -static int sony_nc_rfkill_setup(struct acpi_device *device, - unsigned int handle); -static void sony_nc_rfkill_cleanup(void); static void sony_nc_rfkill_update(void); /*********** Input Devices ***********/ @@ -715,97 +691,59 @@ static struct acpi_device *sony_nc_acpi_device = NULL; /* * acpi_evaluate_object wrappers - * all useful calls into SNC methods take one or zero parameters and return - * integers or arrays. */ -static union acpi_object *__call_snc_method(acpi_handle handle, char *method, - u64 *value) +static int acpi_callgetfunc(acpi_handle handle, char *name, int *result) { - union acpi_object *result = NULL; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer output; + union acpi_object out_obj; acpi_status status; - if (value) { - struct acpi_object_list params; - union acpi_object in; - in.type = ACPI_TYPE_INTEGER; - in.integer.value = *value; - params.count = 1; - params.pointer = ∈ - status = acpi_evaluate_object(handle, method, ¶ms, &output); - dprintk("__call_snc_method: [%s:0x%.8x%.8x]\n", method, - (unsigned int)(*value >> 32), - (unsigned int)*value & 0xffffffff); - } else { - status = acpi_evaluate_object(handle, method, NULL, &output); - dprintk("__call_snc_method: [%s]\n", method); - } - - if (ACPI_FAILURE(status)) { - pr_err("Failed to evaluate [%s]\n", method); - return NULL; - } - - result = (union acpi_object *) output.pointer; - if (!result) - dprintk("No return object [%s]\n", method); - - return result; -} - -static int sony_nc_int_call(acpi_handle handle, char *name, int *value, - int *result) -{ - union acpi_object *object = NULL; - if (value) { - u64 v = *value; - object = __call_snc_method(handle, name, &v); - } else - object = __call_snc_method(handle, name, NULL); - - if (!object) - return -EINVAL; + output.length = sizeof(out_obj); + output.pointer = &out_obj; - if (object->type != ACPI_TYPE_INTEGER) { - pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", - ACPI_TYPE_INTEGER, object->type); - kfree(object); - return -EINVAL; + status = acpi_evaluate_object(handle, name, NULL, &output); + if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) { + *result = out_obj.integer.value; + return 0; } - if (result) - *result = object->integer.value; + pr_warn("acpi_callreadfunc failed\n"); - kfree(object); - return 0; + return -1; } -#define MIN(a, b) (a > b ? b : a) -static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, - void *buffer, size_t buflen) +static int acpi_callsetfunc(acpi_handle handle, char *name, int value, + int *result) { - size_t len = len; - union acpi_object *object = __call_snc_method(handle, name, value); - - if (!object) - return -EINVAL; + struct acpi_object_list params; + union acpi_object in_obj; + struct acpi_buffer output; + union acpi_object out_obj; + acpi_status status; - if (object->type == ACPI_TYPE_BUFFER) - len = MIN(buflen, object->buffer.length); + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = value; - else if (object->type == ACPI_TYPE_INTEGER) - len = MIN(buflen, sizeof(object->integer.value)); + output.length = sizeof(out_obj); + output.pointer = &out_obj; - else { - pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", - ACPI_TYPE_BUFFER, object->type); - kfree(object); - return -EINVAL; + status = acpi_evaluate_object(handle, name, ¶ms, &output); + if (status == AE_OK) { + if (result != NULL) { + if (out_obj.type != ACPI_TYPE_INTEGER) { + pr_warn("acpi_evaluate_object bad return type\n"); + return -1; + } + *result = out_obj.integer.value; + } + return 0; } - memcpy(buffer, object->buffer.pointer, len); - kfree(object); - return 0; + pr_warn("acpi_evaluate_object failed\n"); + + return -1; } struct sony_nc_handles { @@ -832,17 +770,16 @@ static ssize_t sony_nc_handles_show(struct device *dev, static int sony_nc_handles_setup(struct platform_device *pd) { - int i, r, result, arg; + int i; + int result; handles = kzalloc(sizeof(*handles), GFP_KERNEL); if (!handles) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - arg = i + 0x20; - r = sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, - &result); - if (!r) { + if (!acpi_callsetfunc(sony_nc_acpi_handle, + "SN00", i + 0x20, &result)) { dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n", result, i); handles->cap[i] = result; @@ -882,8 +819,8 @@ static int sony_find_snc_handle(int handle) int i; /* not initialized yet, return early */ - if (!handles || !handle) - return -EINVAL; + if (!handles) + return -1; for (i = 0; i < 0x10; i++) { if (handles->cap[i] == handle) { @@ -893,20 +830,21 @@ static int sony_find_snc_handle(int handle) } } dprintk("handle 0x%.4x not found\n", handle); - return -EINVAL; + return -1; } static int sony_call_snc_handle(int handle, int argument, int *result) { - int arg, ret = 0; + int ret = 0; int offset = sony_find_snc_handle(handle); if (offset < 0) - return offset; + return -1; - arg = offset | argument; - ret = sony_nc_int_call(sony_nc_acpi_handle, "SN07", &arg, result); - dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", arg, *result); + ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, + result); + dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument, + *result); return ret; } @@ -951,16 +889,14 @@ static int boolean_validate(const int direction, const int value) static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr, char *buffer) { - int value, ret = 0; + int value; struct sony_nc_value *item = container_of(attr, struct sony_nc_value, devattr); if (!*item->acpiget) return -EIO; - ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiget, NULL, - &value); - if (ret < 0) + if (acpi_callgetfunc(sony_nc_acpi_handle, *item->acpiget, &value) < 0) return -EIO; if (item->validate) @@ -973,8 +909,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, struct device_attribute *attr, const char *buffer, size_t count) { - unsigned long value = 0; - int ret = 0; + int value; struct sony_nc_value *item = container_of(attr, struct sony_nc_value, devattr); @@ -984,8 +919,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; + value = simple_strtoul(buffer, NULL, 10); if (item->validate) value = item->validate(SNC_VALIDATE_IN, value); @@ -993,11 +927,8 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, if (value < 0) return value; - ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset, - (int *)&value, NULL); - if (ret < 0) + if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0) return -EIO; - item->value = value; item->valid = 1; return count; @@ -1017,15 +948,15 @@ struct sony_backlight_props sony_bl_props; static int sony_backlight_update_status(struct backlight_device *bd) { - int arg = bd->props.brightness + 1; - return sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &arg, NULL); + return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", + bd->props.brightness + 1, NULL); } static int sony_backlight_get_brightness(struct backlight_device *bd) { int value; - if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, &value)) + if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) return 0; /* brightness levels are 1-based, while backlight ones are 0-based */ return value - 1; @@ -1093,14 +1024,10 @@ static struct sony_nc_event sony_100_events[] = { { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, { 0x87, SONYPI_EVENT_FNKEY_F7 }, { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, - { 0x88, SONYPI_EVENT_FNKEY_F8 }, - { 0x08, SONYPI_EVENT_FNKEY_RELEASED }, { 0x89, SONYPI_EVENT_FNKEY_F9 }, { 0x09, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8A, SONYPI_EVENT_FNKEY_F10 }, { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, - { 0x8B, SONYPI_EVENT_FNKEY_F11 }, - { 0x0B, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8C, SONYPI_EVENT_FNKEY_F12 }, { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x9d, SONYPI_EVENT_ZOOM_PRESSED }, @@ -1136,116 +1063,63 @@ static struct sony_nc_event sony_127_events[] = { { 0, 0 }, }; -static int sony_nc_hotkeys_decode(u32 event, unsigned int handle) -{ - int ret = -EINVAL; - unsigned int result = 0; - struct sony_nc_event *key_event; - - if (sony_call_snc_handle(handle, 0x200, &result)) { - dprintk("Unable to decode event 0x%.2x 0x%.2x\n", handle, - event); - return -EINVAL; - } - - result &= 0xFF; - - if (handle == 0x0100) - key_event = sony_100_events; - else - key_event = sony_127_events; - - for (; key_event->data; key_event++) { - if (key_event->data == result) { - ret = key_event->event; - break; - } - } - - if (!key_event->data) - pr_info("Unknown hotkey 0x%.2x/0x%.2x (handle 0x%.2x)\n", - event, result, handle); - - return ret; -} - /* * ACPI callbacks */ static void sony_nc_notify(struct acpi_device *device, u32 event) { - u32 real_ev = event; - u8 ev_type = 0; - dprintk("sony_nc_notify, event: 0x%.2x\n", event); - - if (event >= 0x90) { - unsigned int result = 0; - unsigned int arg = 0; - unsigned int handle = 0; - unsigned int offset = event - 0x90; - - if (offset >= ARRAY_SIZE(handles->cap)) { - pr_err("Event 0x%x outside of capabilities list\n", - event); - return; - } - handle = handles->cap[offset]; - - /* list of handles known for generating events */ - switch (handle) { - /* hotkey event */ - case 0x0100: - case 0x0127: - ev_type = 1; - real_ev = sony_nc_hotkeys_decode(event, handle); - - if (real_ev > 0) - sony_laptop_report_input_event(real_ev); - else - /* restore the original event for reporting */ - real_ev = event; - - break; + u32 ev = event; - /* wlan switch */ - case 0x0124: - case 0x0135: - /* events on this handle are reported when the - * switch changes position or for battery - * events. We'll notify both of them but only - * update the rfkill device status when the - * switch is moved. - */ - ev_type = 2; - sony_call_snc_handle(handle, 0x0100, &result); - real_ev = result & 0x03; - - /* hw switch event */ - if (real_ev == 1) - sony_nc_rfkill_update(); - - break; + if (ev >= 0x90) { + /* New-style event */ + int result; + int key_handle = 0; + ev -= 0x90; + + if (sony_find_snc_handle(0x100) == ev) + key_handle = 0x100; + if (sony_find_snc_handle(0x127) == ev) + key_handle = 0x127; + + if (key_handle) { + struct sony_nc_event *key_event; + + if (sony_call_snc_handle(key_handle, 0x200, &result)) { + dprintk("sony_nc_notify, unable to decode" + " event 0x%.2x 0x%.2x\n", key_handle, + ev); + /* restore the original event */ + ev = event; + } else { + ev = result & 0xFF; + + if (key_handle == 0x100) + key_event = sony_100_events; + else + key_event = sony_127_events; + + for (; key_event->data; key_event++) { + if (key_event->data == ev) { + ev = key_event->event; + break; + } + } - default: - dprintk("Unknown event 0x%x for handle 0x%x\n", - event, handle); - break; + if (!key_event->data) + pr_info("Unknown event: 0x%x 0x%x\n", + key_handle, ev); + else + sony_laptop_report_input_event(ev); + } + } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) { + sony_nc_rfkill_update(); + return; } + } else + sony_laptop_report_input_event(ev); - /* clear the event (and the event reason when present) */ - arg = 1 << offset; - sony_nc_int_call(sony_nc_acpi_handle, "SN05", &arg, &result); - - } else { - /* old style event */ - ev_type = 1; - sony_laptop_report_input_event(real_ev); - } - - acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev); - - acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class, - dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev); + dprintk("sony_nc_notify, event: 0x%.2x\n", ev); + acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); } static acpi_status sony_walk_callback(acpi_handle handle, u32 level, @@ -1266,190 +1140,20 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, /* * ACPI device */ -static void sony_nc_function_setup(struct acpi_device *device, - struct platform_device *pf_device) +static int sony_nc_function_setup(struct acpi_device *device) { - unsigned int i, result, bitmask, arg; - - if (!handles) - return; - - /* setup found handles here */ - for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - unsigned int handle = handles->cap[i]; - - if (!handle) - continue; - - dprintk("setting up handle 0x%.4x\n", handle); - - switch (handle) { - case 0x0100: - case 0x0101: - case 0x0127: - /* setup hotkeys */ - sony_call_snc_handle(handle, 0, &result); - break; - case 0x0102: - /* setup hotkeys */ - sony_call_snc_handle(handle, 0x100, &result); - break; - case 0x0105: - case 0x0148: - /* touchpad enable/disable */ - result = sony_nc_touchpad_setup(pf_device, handle); - if (result) - pr_err("couldn't set up touchpad control function (%d)\n", - result); - break; - case 0x0115: - case 0x0136: - case 0x013f: - result = sony_nc_battery_care_setup(pf_device, handle); - if (result) - pr_err("couldn't set up battery care function (%d)\n", - result); - break; - case 0x0119: - result = sony_nc_lid_resume_setup(pf_device); - if (result) - pr_err("couldn't set up lid resume function (%d)\n", - result); - break; - case 0x0122: - result = sony_nc_thermal_setup(pf_device); - if (result) - pr_err("couldn't set up thermal profile function (%d)\n", - result); - break; - case 0x0131: - result = sony_nc_highspeed_charging_setup(pf_device); - if (result) - pr_err("couldn't set up high speed charging function (%d)\n", - result); - break; - case 0x0124: - case 0x0135: - result = sony_nc_rfkill_setup(device, handle); - if (result) - pr_err("couldn't set up rfkill support (%d)\n", - result); - break; - case 0x0137: - case 0x0143: - result = sony_nc_kbd_backlight_setup(pf_device, handle); - if (result) - pr_err("couldn't set up keyboard backlight function (%d)\n", - result); - break; - default: - continue; - } - } + int result; /* Enable all events */ - arg = 0x10; - if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask)) - sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask, - &result); -} - -static void sony_nc_function_cleanup(struct platform_device *pd) -{ - unsigned int i, result, bitmask, handle; - - /* get enabled events and disable them */ - sony_nc_int_call(sony_nc_acpi_handle, "SN01", NULL, &bitmask); - sony_nc_int_call(sony_nc_acpi_handle, "SN03", &bitmask, &result); - - /* cleanup handles here */ - for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - - handle = handles->cap[i]; - - if (!handle) - continue; - - switch (handle) { - case 0x0105: - case 0x0148: - sony_nc_touchpad_cleanup(pd); - break; - case 0x0115: - case 0x0136: - case 0x013f: - sony_nc_battery_care_cleanup(pd); - break; - case 0x0119: - sony_nc_lid_resume_cleanup(pd); - break; - case 0x0122: - sony_nc_thermal_cleanup(pd); - break; - case 0x0131: - sony_nc_highspeed_charging_cleanup(pd); - break; - case 0x0124: - case 0x0135: - sony_nc_rfkill_cleanup(); - break; - case 0x0137: - case 0x0143: - sony_nc_kbd_backlight_cleanup(pd); - break; - default: - continue; - } - } - - /* finally cleanup the handles list */ - sony_nc_handles_cleanup(pd); -} - -static void sony_nc_function_resume(void) -{ - unsigned int i, result, bitmask, arg; - - dprintk("Resuming SNC device\n"); + acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result); - for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - unsigned int handle = handles->cap[i]; - - if (!handle) - continue; - - switch (handle) { - case 0x0100: - case 0x0101: - case 0x0127: - /* re-enable hotkeys */ - sony_call_snc_handle(handle, 0, &result); - break; - case 0x0102: - /* re-enable hotkeys */ - sony_call_snc_handle(handle, 0x100, &result); - break; - case 0x0122: - sony_nc_thermal_resume(); - break; - case 0x0124: - case 0x0135: - sony_nc_rfkill_update(); - break; - case 0x0137: - case 0x0143: - sony_nc_kbd_backlight_resume(); - break; - default: - continue; - } - } + /* Setup hotkeys */ + sony_call_snc_handle(0x0100, 0, &result); + sony_call_snc_handle(0x0101, 0, &result); + sony_call_snc_handle(0x0102, 0x100, &result); + sony_call_snc_handle(0x0127, 0, &result); - /* Enable all events */ - arg = 0x10; - if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask)) - sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask, - &result); + return 0; } static int sony_nc_resume(struct acpi_device *device) @@ -1462,8 +1166,8 @@ static int sony_nc_resume(struct acpi_device *device) if (!item->valid) continue; - ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset, - &item->value, NULL); + ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, + item->value, NULL); if (ret < 0) { pr_err("%s: %d\n", __func__, ret); break; @@ -1472,14 +1176,21 @@ static int sony_nc_resume(struct acpi_device *device) if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { - int arg = 1; - if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) + if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", - &handle))) - sony_nc_function_resume(); + &handle))) { + dprintk("Doing SNC setup\n"); + sony_nc_function_setup(device); + } + + /* re-read rfkill state */ + sony_nc_rfkill_update(); + + /* restore kbd backlight states */ + sony_nc_kbd_backlight_resume(); return 0; } @@ -1502,7 +1213,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) int argument = sony_rfkill_address[(long) data] + 0x100; if (!blocked) - argument |= 0x030000; + argument |= 0xff0000; return sony_call_snc_handle(sony_rfkill_handle, argument, &result); } @@ -1519,7 +1230,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, enum rfkill_type type; const char *name; int result; - bool hwblock, swblock; + bool hwblock; switch (nc_type) { case SONY_WIFI: @@ -1547,21 +1258,8 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, if (!rfk) return -ENOMEM; - if (sony_call_snc_handle(sony_rfkill_handle, 0x200, &result) < 0) { - rfkill_destroy(rfk); - return -1; - } + sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); hwblock = !(result & 0x1); - - if (sony_call_snc_handle(sony_rfkill_handle, - sony_rfkill_address[nc_type], - &result) < 0) { - rfkill_destroy(rfk); - return -1; - } - swblock = !(result & 0x2); - - rfkill_init_sw_state(rfk, swblock); rfkill_set_hw_state(rfk, hwblock); err = rfkill_register(rfk); @@ -1597,79 +1295,101 @@ static void sony_nc_rfkill_update(void) sony_call_snc_handle(sony_rfkill_handle, argument, &result); rfkill_set_states(sony_rfkill_devices[i], - !(result & 0x2), false); + !(result & 0xf), false); } } -static int sony_nc_rfkill_setup(struct acpi_device *device, - unsigned int handle) +static void sony_nc_rfkill_setup(struct acpi_device *device) { - u64 offset; - int i; - unsigned char buffer[32] = { 0 }; + int offset; + u8 dev_code, i; + acpi_status status; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *device_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + offset = sony_find_snc_handle(0x124); + if (offset == -1) { + offset = sony_find_snc_handle(0x135); + if (offset == -1) + return; + else + sony_rfkill_handle = 0x135; + } else + sony_rfkill_handle = 0x124; + dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle); - offset = sony_find_snc_handle(handle); - sony_rfkill_handle = handle; - - i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer, - 32); - if (i < 0) - return i; - - /* The buffer is filled with magic numbers describing the devices - * available, 0xff terminates the enumeration. - * Known codes: - * 0x00 WLAN - * 0x10 BLUETOOTH - * 0x20 WWAN GPRS-EDGE - * 0x21 WWAN HSDPA - * 0x22 WWAN EV-DO - * 0x23 WWAN GPS - * 0x25 Gobi WWAN no GPS - * 0x26 Gobi WWAN + GPS - * 0x28 Gobi WWAN no GPS - * 0x29 Gobi WWAN + GPS - * 0x30 WIMAX - * 0x50 Gobi WWAN no GPS - * 0x51 Gobi WWAN + GPS - * 0x70 no SIM card slot - * 0x71 SIM card slot + /* need to read the whole buffer returned by the acpi call to SN06 + * here otherwise we may miss some features + */ + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = offset; + status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) { + dprintk("Radio device enumeration failed\n"); + return; + } + + device_enum = (union acpi_object *) buffer.pointer; + if (!device_enum) { + pr_err("No SN06 return object\n"); + goto out_no_enum; + } + if (device_enum->type != ACPI_TYPE_BUFFER) { + pr_err("Invalid SN06 return object 0x%.2x\n", + device_enum->type); + goto out_no_enum; + } + + /* the buffer is filled with magic numbers describing the devices + * available, 0xff terminates the enumeration */ - for (i = 0; i < ARRAY_SIZE(buffer); i++) { + for (i = 0; i < device_enum->buffer.length; i++) { - if (buffer[i] == 0xff) + dev_code = *(device_enum->buffer.pointer + i); + if (dev_code == 0xff) break; - dprintk("Radio devices, found 0x%.2x\n", buffer[i]); + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); - if (buffer[i] == 0 && !sony_rfkill_devices[SONY_WIFI]) + if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) sony_nc_setup_rfkill(device, SONY_WIFI); - if (buffer[i] == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) + if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) sony_nc_setup_rfkill(device, SONY_BLUETOOTH); - if (((0xf0 & buffer[i]) == 0x20 || - (0xf0 & buffer[i]) == 0x50) && + if ((0xf0 & dev_code) == 0x20 && !sony_rfkill_devices[SONY_WWAN]) sony_nc_setup_rfkill(device, SONY_WWAN); - if (buffer[i] == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) + if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) sony_nc_setup_rfkill(device, SONY_WIMAX); } - return 0; + +out_no_enum: + kfree(buffer.pointer); + return; } /* Keyboard backlight feature */ +#define KBDBL_HANDLER 0x137 +#define KBDBL_PRESENT 0xB00 +#define SET_MODE 0xC00 +#define SET_STATE 0xD00 +#define SET_TIMEOUT 0xE00 + struct kbd_backlight { - unsigned int handle; - unsigned int base; - unsigned int mode; - unsigned int timeout; + int mode; + int timeout; struct device_attribute mode_attr; struct device_attribute timeout_attr; }; -static struct kbd_backlight *kbdbl_ctl; +static struct kbd_backlight *kbdbl_handle; static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) { @@ -1678,15 +1398,15 @@ static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) if (value > 1) return -EINVAL; - if (sony_call_snc_handle(kbdbl_ctl->handle, - (value << 0x10) | (kbdbl_ctl->base), &result)) + if (sony_call_snc_handle(KBDBL_HANDLER, + (value << 0x10) | SET_MODE, &result)) return -EIO; /* Try to turn the light on/off immediately */ - sony_call_snc_handle(kbdbl_ctl->handle, - (value << 0x10) | (kbdbl_ctl->base + 0x100), &result); + sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE, + &result); - kbdbl_ctl->mode = value; + kbdbl_handle->mode = value; return 0; } @@ -1701,7 +1421,7 @@ static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) + if (strict_strtoul(buffer, 10, &value)) return -EINVAL; ret = __sony_nc_kbd_backlight_mode_set(value); @@ -1715,7 +1435,7 @@ static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev, struct device_attribute *attr, char *buffer) { ssize_t count = 0; - count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->mode); + count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode); return count; } @@ -1726,11 +1446,11 @@ static int __sony_nc_kbd_backlight_timeout_set(u8 value) if (value > 3) return -EINVAL; - if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) | - (kbdbl_ctl->base + 0x200), &result)) + if (sony_call_snc_handle(KBDBL_HANDLER, + (value << 0x10) | SET_TIMEOUT, &result)) return -EIO; - kbdbl_ctl->timeout = value; + kbdbl_handle->timeout = value; return 0; } @@ -1745,7 +1465,7 @@ static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) + if (strict_strtoul(buffer, 10, &value)) return -EINVAL; ret = __sony_nc_kbd_backlight_timeout_set(value); @@ -1759,58 +1479,39 @@ static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev, struct device_attribute *attr, char *buffer) { ssize_t count = 0; - count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->timeout); + count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout); return count; } -static int sony_nc_kbd_backlight_setup(struct platform_device *pd, - unsigned int handle) +static int sony_nc_kbd_backlight_setup(struct platform_device *pd) { int result; - int ret = 0; - - /* verify the kbd backlight presence, these handles are not used for - * keyboard backlight only - */ - ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100, - &result); - if (ret) - return ret; - if ((handle == 0x0137 && !(result & 0x02)) || - !(result & 0x01)) { - dprintk("no backlight keyboard found\n"); + if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result)) + return 0; + if (!(result & 0x02)) return 0; - } - kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL); - if (!kbdbl_ctl) + kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL); + if (!kbdbl_handle) return -ENOMEM; - kbdbl_ctl->handle = handle; - if (handle == 0x0137) - kbdbl_ctl->base = 0x0C00; - else - kbdbl_ctl->base = 0x4000; - - sysfs_attr_init(&kbdbl_ctl->mode_attr.attr); - kbdbl_ctl->mode_attr.attr.name = "kbd_backlight"; - kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR; - kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show; - kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store; + sysfs_attr_init(&kbdbl_handle->mode_attr.attr); + kbdbl_handle->mode_attr.attr.name = "kbd_backlight"; + kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR; + kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show; + kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store; - sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr); - kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout"; - kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; - kbdbl_ctl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; - kbdbl_ctl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; + sysfs_attr_init(&kbdbl_handle->timeout_attr.attr); + kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout"; + kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; + kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; + kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; - ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr); - if (ret) + if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr)) goto outkzalloc; - ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr); - if (ret) + if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr)) goto outmode; __sony_nc_kbd_backlight_mode_set(kbd_backlight); @@ -1819,711 +1520,126 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd, return 0; outmode: - device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); + device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); outkzalloc: - kfree(kbdbl_ctl); - kbdbl_ctl = NULL; - return ret; + kfree(kbdbl_handle); + kbdbl_handle = NULL; + return -1; } -static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd) +static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) { - if (kbdbl_ctl) { + if (kbdbl_handle) { int result; - device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); - device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr); + device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); + device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr); /* restore the default hw behaviour */ - sony_call_snc_handle(kbdbl_ctl->handle, - kbdbl_ctl->base | 0x10000, &result); - sony_call_snc_handle(kbdbl_ctl->handle, - kbdbl_ctl->base + 0x200, &result); + sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result); + sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result); - kfree(kbdbl_ctl); - kbdbl_ctl = NULL; + kfree(kbdbl_handle); } + return 0; } static void sony_nc_kbd_backlight_resume(void) { int ignore = 0; - if (!kbdbl_ctl) + if (!kbdbl_handle) return; - if (kbdbl_ctl->mode == 0) - sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base, - &ignore); + if (kbdbl_handle->mode == 0) + sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore); - if (kbdbl_ctl->timeout != 0) - sony_call_snc_handle(kbdbl_ctl->handle, - (kbdbl_ctl->base + 0x200) | - (kbdbl_ctl->timeout << 0x10), &ignore); + if (kbdbl_handle->timeout != 0) + sony_call_snc_handle(KBDBL_HANDLER, + (kbdbl_handle->timeout << 0x10) | SET_TIMEOUT, + &ignore); } -struct battery_care_control { - struct device_attribute attrs[2]; - unsigned int handle; -}; -static struct battery_care_control *bcare_ctl; - -static ssize_t sony_nc_battery_care_limit_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) +static void sony_nc_backlight_ng_read_limits(int handle, + struct sony_backlight_props *props) { - unsigned int result, cmd; - unsigned long value; - - if (count > 31) - return -EINVAL; + int offset; + acpi_status status; + u8 brlvl, i; + u8 min = 0xff, max = 0x00; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *lvl_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; + props->handle = handle; + props->offset = 0; + props->maxlvl = 0xff; - /* limit values (2 bits): - * 00 - none - * 01 - 80% - * 10 - 50% - * 11 - 100% - * - * bit 0: 0 disable BCL, 1 enable BCL - * bit 1: 1 tell to store the battery limit (see bits 6,7) too - * bits 2,3: reserved - * bits 4,5: store the limit into the EC - * bits 6,7: store the limit into the battery - */ + offset = sony_find_snc_handle(handle); + if (offset < 0) + return; - /* - * handle 0x0115 should allow storing on battery too; - * handle 0x0136 same as 0x0115 + health status; - * handle 0x013f, same as 0x0136 but no storing on the battery - * - * Store only inside the EC for now, regardless the handle number + /* try to read the boundaries from ACPI tables, if we fail the above + * defaults should be reasonable */ - if (value == 0) - /* disable limits */ - cmd = 0x0; + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = offset; + status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) + return; - else if (value <= 50) - cmd = 0x21; + lvl_enum = (union acpi_object *) buffer.pointer; + if (!lvl_enum) { + pr_err("No SN06 return object."); + return; + } + if (lvl_enum->type != ACPI_TYPE_BUFFER) { + pr_err("Invalid SN06 return object 0x%.2x\n", + lvl_enum->type); + goto out_invalid; + } - else if (value <= 80) - cmd = 0x11; + /* the buffer lists brightness levels available, brightness levels are + * from 0 to 8 in the array, other values are used by ALS control. + */ + for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) { - else if (value <= 100) - cmd = 0x31; + brlvl = *(lvl_enum->buffer.pointer + i); + dprintk("Brightness level: %d\n", brlvl); - else - return -EINVAL; + if (!brlvl) + break; - if (sony_call_snc_handle(bcare_ctl->handle, (cmd << 0x10) | 0x0100, - &result)) - return -EIO; + if (brlvl > max) + max = brlvl; + if (brlvl < min) + min = brlvl; + } + props->offset = min; + props->maxlvl = max; + dprintk("Brightness levels: min=%d max=%d\n", props->offset, + props->maxlvl); - return count; +out_invalid: + kfree(buffer.pointer); + return; } -static ssize_t sony_nc_battery_care_limit_show(struct device *dev, - struct device_attribute *attr, char *buffer) +static void sony_nc_backlight_setup(void) { - unsigned int result, status; + acpi_handle unused; + int max_brightness = 0; + const struct backlight_ops *ops = NULL; + struct backlight_properties props; - if (sony_call_snc_handle(bcare_ctl->handle, 0x0000, &result)) - return -EIO; - - status = (result & 0x01) ? ((result & 0x30) >> 0x04) : 0; - switch (status) { - case 1: - status = 80; - break; - case 2: - status = 50; - break; - case 3: - status = 100; - break; - default: - status = 0; - break; - } - - return snprintf(buffer, PAGE_SIZE, "%d\n", status); -} - -static ssize_t sony_nc_battery_care_health_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - ssize_t count = 0; - unsigned int health; - - if (sony_call_snc_handle(bcare_ctl->handle, 0x0200, &health)) - return -EIO; - - count = snprintf(buffer, PAGE_SIZE, "%d\n", health & 0xff); - - return count; -} - -static int sony_nc_battery_care_setup(struct platform_device *pd, - unsigned int handle) -{ - int ret = 0; - - bcare_ctl = kzalloc(sizeof(struct battery_care_control), GFP_KERNEL); - if (!bcare_ctl) - return -ENOMEM; - - bcare_ctl->handle = handle; - - sysfs_attr_init(&bcare_ctl->attrs[0].attr); - bcare_ctl->attrs[0].attr.name = "battery_care_limiter"; - bcare_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR; - bcare_ctl->attrs[0].show = sony_nc_battery_care_limit_show; - bcare_ctl->attrs[0].store = sony_nc_battery_care_limit_store; - - ret = device_create_file(&pd->dev, &bcare_ctl->attrs[0]); - if (ret) - goto outkzalloc; - - /* 0x0115 is for models with no health reporting capability */ - if (handle == 0x0115) - return 0; - - sysfs_attr_init(&bcare_ctl->attrs[1].attr); - bcare_ctl->attrs[1].attr.name = "battery_care_health"; - bcare_ctl->attrs[1].attr.mode = S_IRUGO; - bcare_ctl->attrs[1].show = sony_nc_battery_care_health_show; - - ret = device_create_file(&pd->dev, &bcare_ctl->attrs[1]); - if (ret) - goto outlimiter; - - return 0; - -outlimiter: - device_remove_file(&pd->dev, &bcare_ctl->attrs[0]); - -outkzalloc: - kfree(bcare_ctl); - bcare_ctl = NULL; - - return ret; -} - -static void sony_nc_battery_care_cleanup(struct platform_device *pd) -{ - if (bcare_ctl) { - device_remove_file(&pd->dev, &bcare_ctl->attrs[0]); - if (bcare_ctl->handle != 0x0115) - device_remove_file(&pd->dev, &bcare_ctl->attrs[1]); - - kfree(bcare_ctl); - bcare_ctl = NULL; - } -} - -struct snc_thermal_ctrl { - unsigned int mode; - unsigned int profiles; - struct device_attribute mode_attr; - struct device_attribute profiles_attr; -}; -static struct snc_thermal_ctrl *th_handle; - -#define THM_PROFILE_MAX 3 -static const char * const snc_thermal_profiles[] = { - "balanced", - "silent", - "performance" -}; - -static int sony_nc_thermal_mode_set(unsigned short mode) -{ - unsigned int result; - - /* the thermal profile seems to be a two bit bitmask: - * lsb -> silent - * msb -> performance - * no bit set is the normal operation and is always valid - * Some vaio models only have "balanced" and "performance" - */ - if ((mode && !(th_handle->profiles & mode)) || mode >= THM_PROFILE_MAX) - return -EINVAL; - - if (sony_call_snc_handle(0x0122, mode << 0x10 | 0x0200, &result)) - return -EIO; - - th_handle->mode = mode; - - return 0; -} - -static int sony_nc_thermal_mode_get(void) -{ - unsigned int result; - - if (sony_call_snc_handle(0x0122, 0x0100, &result)) - return -EIO; - - return result & 0xff; -} - -static ssize_t sony_nc_thermal_profiles_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - short cnt; - size_t idx = 0; - - for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) { - if (!cnt || (th_handle->profiles & cnt)) - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "%s ", - snc_thermal_profiles[cnt]); - } - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "\n"); - - return idx; -} - -static ssize_t sony_nc_thermal_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) -{ - unsigned short cmd; - size_t len = count; - - if (count == 0) - return -EINVAL; - - /* skip the newline if present */ - if (buffer[len - 1] == '\n') - len--; - - for (cmd = 0; cmd < THM_PROFILE_MAX; cmd++) - if (strncmp(buffer, snc_thermal_profiles[cmd], len) == 0) - break; - - if (sony_nc_thermal_mode_set(cmd)) - return -EIO; - - return count; -} - -static ssize_t sony_nc_thermal_mode_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - ssize_t count = 0; - unsigned int mode = sony_nc_thermal_mode_get(); - - if (mode < 0) - return mode; - - count = snprintf(buffer, PAGE_SIZE, "%s\n", snc_thermal_profiles[mode]); - - return count; -} - -static int sony_nc_thermal_setup(struct platform_device *pd) -{ - int ret = 0; - th_handle = kzalloc(sizeof(struct snc_thermal_ctrl), GFP_KERNEL); - if (!th_handle) - return -ENOMEM; - - ret = sony_call_snc_handle(0x0122, 0x0000, &th_handle->profiles); - if (ret) { - pr_warn("couldn't to read the thermal profiles\n"); - goto outkzalloc; - } - - ret = sony_nc_thermal_mode_get(); - if (ret < 0) { - pr_warn("couldn't to read the current thermal profile"); - goto outkzalloc; - } - th_handle->mode = ret; - - sysfs_attr_init(&th_handle->profiles_attr.attr); - th_handle->profiles_attr.attr.name = "thermal_profiles"; - th_handle->profiles_attr.attr.mode = S_IRUGO; - th_handle->profiles_attr.show = sony_nc_thermal_profiles_show; - - sysfs_attr_init(&th_handle->mode_attr.attr); - th_handle->mode_attr.attr.name = "thermal_control"; - th_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR; - th_handle->mode_attr.show = sony_nc_thermal_mode_show; - th_handle->mode_attr.store = sony_nc_thermal_mode_store; - - ret = device_create_file(&pd->dev, &th_handle->profiles_attr); - if (ret) - goto outkzalloc; - - ret = device_create_file(&pd->dev, &th_handle->mode_attr); - if (ret) - goto outprofiles; - - return 0; - -outprofiles: - device_remove_file(&pd->dev, &th_handle->profiles_attr); -outkzalloc: - kfree(th_handle); - th_handle = NULL; - return ret; -} - -static void sony_nc_thermal_cleanup(struct platform_device *pd) -{ - if (th_handle) { - device_remove_file(&pd->dev, &th_handle->profiles_attr); - device_remove_file(&pd->dev, &th_handle->mode_attr); - kfree(th_handle); - th_handle = NULL; - } -} - -static void sony_nc_thermal_resume(void) -{ - unsigned int status = sony_nc_thermal_mode_get(); - - if (status != th_handle->mode) - sony_nc_thermal_mode_set(th_handle->mode); -} - -/* resume on LID open */ -struct snc_lid_resume_control { - struct device_attribute attrs[3]; - unsigned int status; -}; -static struct snc_lid_resume_control *lid_ctl; - -static ssize_t sony_nc_lid_resume_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) -{ - unsigned int result, pos; - unsigned long value; - if (count > 31) - return -EINVAL; - - if (kstrtoul(buffer, 10, &value) || value > 1) - return -EINVAL; - - /* the value we have to write to SNC is a bitmask: - * +--------------+ - * | S3 | S4 | S5 | - * +--------------+ - * 2 1 0 - */ - if (strcmp(attr->attr.name, "lid_resume_S3") == 0) - pos = 2; - else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) - pos = 1; - else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) - pos = 0; - else - return -EINVAL; - - if (value) - value = lid_ctl->status | (1 << pos); - else - value = lid_ctl->status & ~(1 << pos); - - if (sony_call_snc_handle(0x0119, value << 0x10 | 0x0100, &result)) - return -EIO; - - lid_ctl->status = value; - - return count; -} - -static ssize_t sony_nc_lid_resume_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - unsigned int pos; - - if (strcmp(attr->attr.name, "lid_resume_S3") == 0) - pos = 2; - else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) - pos = 1; - else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) - pos = 0; - else - return -EINVAL; - - return snprintf(buffer, PAGE_SIZE, "%d\n", - (lid_ctl->status >> pos) & 0x01); -} - -static int sony_nc_lid_resume_setup(struct platform_device *pd) -{ - unsigned int result; - int i; - - if (sony_call_snc_handle(0x0119, 0x0000, &result)) - return -EIO; - - lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL); - if (!lid_ctl) - return -ENOMEM; - - lid_ctl->status = result & 0x7; - - sysfs_attr_init(&lid_ctl->attrs[0].attr); - lid_ctl->attrs[0].attr.name = "lid_resume_S3"; - lid_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR; - lid_ctl->attrs[0].show = sony_nc_lid_resume_show; - lid_ctl->attrs[0].store = sony_nc_lid_resume_store; - - sysfs_attr_init(&lid_ctl->attrs[1].attr); - lid_ctl->attrs[1].attr.name = "lid_resume_S4"; - lid_ctl->attrs[1].attr.mode = S_IRUGO | S_IWUSR; - lid_ctl->attrs[1].show = sony_nc_lid_resume_show; - lid_ctl->attrs[1].store = sony_nc_lid_resume_store; - - sysfs_attr_init(&lid_ctl->attrs[2].attr); - lid_ctl->attrs[2].attr.name = "lid_resume_S5"; - lid_ctl->attrs[2].attr.mode = S_IRUGO | S_IWUSR; - lid_ctl->attrs[2].show = sony_nc_lid_resume_show; - lid_ctl->attrs[2].store = sony_nc_lid_resume_store; - - for (i = 0; i < 3; i++) { - result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); - if (result) - goto liderror; - } - - return 0; - -liderror: - for (; i > 0; i--) - device_remove_file(&pd->dev, &lid_ctl->attrs[i]); - - kfree(lid_ctl); - lid_ctl = NULL; - - return result; -} - -static void sony_nc_lid_resume_cleanup(struct platform_device *pd) -{ - int i; - - if (lid_ctl) { - for (i = 0; i < 3; i++) - device_remove_file(&pd->dev, &lid_ctl->attrs[i]); - - kfree(lid_ctl); - lid_ctl = NULL; - } -} - -/* High speed charging function */ -static struct device_attribute *hsc_handle; - -static ssize_t sony_nc_highspeed_charging_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) -{ - unsigned int result; - unsigned long value; - - if (count > 31) - return -EINVAL; - - if (kstrtoul(buffer, 10, &value) || value > 1) - return -EINVAL; - - if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result)) - return -EIO; - - return count; -} - -static ssize_t sony_nc_highspeed_charging_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - unsigned int result; - - if (sony_call_snc_handle(0x0131, 0x0100, &result)) - return -EIO; - - return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01); -} - -static int sony_nc_highspeed_charging_setup(struct platform_device *pd) -{ - unsigned int result; - - if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) { - /* some models advertise the handle but have no implementation - * for it - */ - pr_info("No High Speed Charging capability found\n"); - return 0; - } - - hsc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL); - if (!hsc_handle) - return -ENOMEM; - - sysfs_attr_init(&hsc_handle->attr); - hsc_handle->attr.name = "battery_highspeed_charging"; - hsc_handle->attr.mode = S_IRUGO | S_IWUSR; - hsc_handle->show = sony_nc_highspeed_charging_show; - hsc_handle->store = sony_nc_highspeed_charging_store; - - result = device_create_file(&pd->dev, hsc_handle); - if (result) { - kfree(hsc_handle); - hsc_handle = NULL; - return result; - } - - return 0; -} - -static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd) -{ - if (hsc_handle) { - device_remove_file(&pd->dev, hsc_handle); - kfree(hsc_handle); - hsc_handle = NULL; - } -} - -/* Touchpad enable/disable */ -struct touchpad_control { - struct device_attribute attr; - int handle; -}; -static struct touchpad_control *tp_ctl; - -static ssize_t sony_nc_touchpad_store(struct device *dev, - struct device_attribute *attr, const char *buffer, size_t count) -{ - unsigned int result; - unsigned long value; - - if (count > 31) - return -EINVAL; - - if (kstrtoul(buffer, 10, &value) || value > 1) - return -EINVAL; - - /* sysfs: 0 disabled, 1 enabled - * EC: 0 enabled, 1 disabled - */ - if (sony_call_snc_handle(tp_ctl->handle, - (!value << 0x10) | 0x100, &result)) - return -EIO; - - return count; -} - -static ssize_t sony_nc_touchpad_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - unsigned int result; - - if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result)) - return -EINVAL; - - return snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01)); -} - -static int sony_nc_touchpad_setup(struct platform_device *pd, - unsigned int handle) -{ - int ret = 0; - - tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL); - if (!tp_ctl) - return -ENOMEM; - - tp_ctl->handle = handle; - - sysfs_attr_init(&tp_ctl->attr.attr); - tp_ctl->attr.attr.name = "touchpad"; - tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR; - tp_ctl->attr.show = sony_nc_touchpad_show; - tp_ctl->attr.store = sony_nc_touchpad_store; - - ret = device_create_file(&pd->dev, &tp_ctl->attr); - if (ret) { - kfree(tp_ctl); - tp_ctl = NULL; - } - - return ret; -} - -static void sony_nc_touchpad_cleanup(struct platform_device *pd) -{ - if (tp_ctl) { - device_remove_file(&pd->dev, &tp_ctl->attr); - kfree(tp_ctl); - tp_ctl = NULL; - } -} - -static void sony_nc_backlight_ng_read_limits(int handle, - struct sony_backlight_props *props) -{ - u64 offset; - int i; - u8 min = 0xff, max = 0x00; - unsigned char buffer[32] = { 0 }; - - props->handle = handle; - props->offset = 0; - props->maxlvl = 0xff; - - offset = sony_find_snc_handle(handle); - if (offset < 0) - return; - - /* try to read the boundaries from ACPI tables, if we fail the above - * defaults should be reasonable - */ - i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer, - 32); - if (i < 0) - return; - - /* the buffer lists brightness levels available, brightness levels are - * from position 0 to 8 in the array, other values are used by ALS - * control. - */ - for (i = 0; i < 9 && i < ARRAY_SIZE(buffer); i++) { - - dprintk("Brightness level: %d\n", buffer[i]); - - if (!buffer[i]) - break; - - if (buffer[i] > max) - max = buffer[i]; - if (buffer[i] < min) - min = buffer[i]; - } - props->offset = min; - props->maxlvl = max; - dprintk("Brightness levels: min=%d max=%d\n", props->offset, - props->maxlvl); -} - -static void sony_nc_backlight_setup(void) -{ - acpi_handle unused; - int max_brightness = 0; - const struct backlight_ops *ops = NULL; - struct backlight_properties props; - - if (sony_find_snc_handle(0x12f) != -1) { - ops = &sony_backlight_ng_ops; - sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props); - max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + if (sony_find_snc_handle(0x12f) != -1) { + ops = &sony_backlight_ng_ops; + sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props); + max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; } else if (sony_find_snc_handle(0x137) != -1) { ops = &sony_backlight_ng_ops; @@ -2599,25 +1715,28 @@ static int sony_nc_add(struct acpi_device *device) if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { - int arg = 1; - if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) + if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); - /* retrieve the available handles */ result = sony_nc_handles_setup(sony_pf_device); - if (!result) - sony_nc_function_setup(device, sony_pf_device); + if (result) + goto outpresent; + result = sony_nc_kbd_backlight_setup(sony_pf_device); + if (result) + goto outsnc; + sony_nc_function_setup(device); + sony_nc_rfkill_setup(device); } /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); if (result) { pr_err("Unable to create input devices\n"); - goto outsnc; + goto outkbdbacklight; } if (acpi_video_backlight_support()) { @@ -2675,8 +1794,10 @@ static int sony_nc_add(struct acpi_device *device) sony_laptop_remove_input(); + outkbdbacklight: + sony_nc_kbd_backlight_cleanup(sony_pf_device); + outsnc: - sony_nc_function_cleanup(sony_pf_device); sony_nc_handles_cleanup(sony_pf_device); outpresent: @@ -2699,10 +1820,11 @@ static int sony_nc_remove(struct acpi_device *device, int type) device_remove_file(&sony_pf_device->dev, &item->devattr); } - sony_nc_function_cleanup(sony_pf_device); + sony_nc_kbd_backlight_cleanup(sony_pf_device); sony_nc_handles_cleanup(sony_pf_device); sony_pf_remove(); sony_laptop_remove_input(); + sony_nc_rfkill_cleanup(); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); return 0; @@ -3315,9 +2437,7 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; - + value = simple_strtoul(buffer, NULL, 10); mutex_lock(&spic_dev.lock); __sony_pic_set_wwanpower(value); mutex_unlock(&spic_dev.lock); @@ -3354,9 +2474,7 @@ static ssize_t sony_pic_bluetoothpower_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; - + value = simple_strtoul(buffer, NULL, 10); mutex_lock(&spic_dev.lock); __sony_pic_set_bluetoothpower(value); mutex_unlock(&spic_dev.lock); @@ -3395,9 +2513,7 @@ static ssize_t sony_pic_fanspeed_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; - + value = simple_strtoul(buffer, NULL, 10); if (sony_pic_set_fanspeed(value)) return -EIO; @@ -3555,8 +2671,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ret = -EIO; break; } - if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, - &value)) { + if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) { ret = -EIO; break; } @@ -3573,9 +2688,8 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ret = -EFAULT; break; } - value = (val8 >> 5) + 1; - if (sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &value, - NULL)) { + if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", + (val8 >> 5) + 1, NULL)) { ret = -EIO; break; } diff --git a/trunk/drivers/platform/x86/thinkpad_acpi.c b/trunk/drivers/platform/x86/thinkpad_acpi.c index 8b5610d88418..d68c0002f4a2 100644 --- a/trunk/drivers/platform/x86/thinkpad_acpi.c +++ b/trunk/drivers/platform/x86/thinkpad_acpi.c @@ -3402,7 +3402,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) /* Do not issue duplicate brightness change events to * userspace. tpacpi_detect_brightness_capabilities() must have * been called before this point */ - if (acpi_video_backlight_support()) { + if (tp_features.bright_acpimode && acpi_video_backlight_support()) { pr_info("This ThinkPad has standard ACPI backlight " "brightness control, supported by the ACPI " "video driver\n"); diff --git a/trunk/drivers/platform/x86/toshiba_acpi.c b/trunk/drivers/platform/x86/toshiba_acpi.c index dab10f6edcd4..57787d87d9a4 100644 --- a/trunk/drivers/platform/x86/toshiba_acpi.c +++ b/trunk/drivers/platform/x86/toshiba_acpi.c @@ -95,7 +95,6 @@ MODULE_LICENSE("GPL"); /* registers */ #define HCI_FAN 0x0004 -#define HCI_TR_BACKLIGHT 0x0005 #define HCI_SYSTEM_EVENT 0x0016 #define HCI_VIDEO_OUT 0x001c #define HCI_HOTKEY_EVENT 0x001e @@ -135,7 +134,6 @@ struct toshiba_acpi_dev { unsigned int system_event_supported:1; unsigned int ntfy_supported:1; unsigned int info_supported:1; - unsigned int tr_backlight_supported:1; struct mutex mutex; }; @@ -480,70 +478,34 @@ static const struct rfkill_ops toshiba_rfk_ops = { .poll = bt_rfkill_poll, }; -static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled) -{ - u32 hci_result; - u32 status; - - hci_read1(dev, HCI_TR_BACKLIGHT, &status, &hci_result); - *enabled = !status; - return hci_result == HCI_SUCCESS ? 0 : -EIO; -} - -static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable) -{ - u32 hci_result; - u32 value = !enable; - - hci_write1(dev, HCI_TR_BACKLIGHT, value, &hci_result); - return hci_result == HCI_SUCCESS ? 0 : -EIO; -} - static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; -static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) +static int get_lcd(struct backlight_device *bd) { + struct toshiba_acpi_dev *dev = bl_get_data(bd); u32 hci_result; u32 value; - int brightness = 0; - - if (dev->tr_backlight_supported) { - bool enabled; - int ret = get_tr_backlight_status(dev, &enabled); - if (ret) - return ret; - if (enabled) - return 0; - brightness++; - } hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result); if (hci_result == HCI_SUCCESS) - return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT); + return (value >> HCI_LCD_BRIGHTNESS_SHIFT); return -EIO; } -static int get_lcd_brightness(struct backlight_device *bd) -{ - struct toshiba_acpi_dev *dev = bl_get_data(bd); - return __get_lcd_brightness(dev); -} - static int lcd_proc_show(struct seq_file *m, void *v) { struct toshiba_acpi_dev *dev = m->private; int value; - int levels; if (!dev->backlight_dev) return -ENODEV; - levels = dev->backlight_dev->props.max_brightness + 1; - value = get_lcd_brightness(dev->backlight_dev); + value = get_lcd(dev->backlight_dev); if (value >= 0) { seq_printf(m, "brightness: %d\n", value); - seq_printf(m, "brightness_levels: %d\n", levels); + seq_printf(m, "brightness_levels: %d\n", + HCI_LCD_BRIGHTNESS_LEVELS); return 0; } @@ -556,19 +518,10 @@ static int lcd_proc_open(struct inode *inode, struct file *file) return single_open(file, lcd_proc_show, PDE(inode)->data); } -static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) +static int set_lcd(struct toshiba_acpi_dev *dev, int value) { u32 hci_result; - if (dev->tr_backlight_supported) { - bool enable = !value; - int ret = set_tr_backlight_status(dev, enable); - if (ret) - return ret; - if (value) - value--; - } - value = value << HCI_LCD_BRIGHTNESS_SHIFT; hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); return hci_result == HCI_SUCCESS ? 0 : -EIO; @@ -577,7 +530,7 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) static int set_lcd_status(struct backlight_device *bd) { struct toshiba_acpi_dev *dev = bl_get_data(bd); - return set_lcd_brightness(dev, bd->props.brightness); + return set_lcd(dev, bd->props.brightness); } static ssize_t lcd_proc_write(struct file *file, const char __user *buf, @@ -588,7 +541,6 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf, size_t len; int value; int ret; - int levels = dev->backlight_dev->props.max_brightness + 1; len = min(count, sizeof(cmd) - 1); if (copy_from_user(cmd, buf, len)) @@ -596,8 +548,8 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf, cmd[len] = '\0'; if (sscanf(cmd, " brightness : %i", &value) == 1 && - value >= 0 && value < levels) { - ret = set_lcd_brightness(dev, value); + value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { + ret = set_lcd(dev, value); if (ret == 0) ret = count; } else { @@ -908,9 +860,8 @@ static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev) } static const struct backlight_ops toshiba_backlight_data = { - .options = BL_CORE_SUSPENDRESUME, - .get_brightness = get_lcd_brightness, - .update_status = set_lcd_status, + .get_brightness = get_lcd, + .update_status = set_lcd_status, }; static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, @@ -1069,56 +1020,6 @@ static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) return error; } -static int __devinit toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) -{ - struct backlight_properties props; - int brightness; - int ret; - bool enabled; - - /* - * Some machines don't support the backlight methods at all, and - * others support it read-only. Either of these is pretty useless, - * so only register the backlight device if the backlight method - * supports both reads and writes. - */ - brightness = __get_lcd_brightness(dev); - if (brightness < 0) - return 0; - ret = set_lcd_brightness(dev, brightness); - if (ret) { - pr_debug("Backlight method is read-only, disabling backlight support\n"); - return 0; - } - - /* Determine whether or not BIOS supports transflective backlight */ - ret = get_tr_backlight_status(dev, &enabled); - dev->tr_backlight_supported = !ret; - - memset(&props, 0, sizeof(props)); - props.type = BACKLIGHT_PLATFORM; - props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; - - /* adding an extra level and having 0 change to transflective mode */ - if (dev->tr_backlight_supported) - props.max_brightness++; - - dev->backlight_dev = backlight_device_register("toshiba", - &dev->acpi_dev->dev, - dev, - &toshiba_backlight_data, - &props); - if (IS_ERR(dev->backlight_dev)) { - ret = PTR_ERR(dev->backlight_dev); - pr_err("Could not register toshiba backlight device\n"); - dev->backlight_dev = NULL; - return ret; - } - - dev->backlight_dev->props.brightness = brightness; - return 0; -} - static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); @@ -1177,6 +1078,7 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) u32 dummy; bool bt_present; int ret = 0; + struct backlight_properties props; if (toshiba_acpi) return -EBUSY; @@ -1202,9 +1104,22 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) mutex_init(&dev->mutex); - ret = toshiba_acpi_setup_backlight(dev); - if (ret) + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_PLATFORM; + props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; + dev->backlight_dev = backlight_device_register("toshiba", + &acpi_dev->dev, + dev, + &toshiba_backlight_data, + &props); + if (IS_ERR(dev->backlight_dev)) { + ret = PTR_ERR(dev->backlight_dev); + + pr_err("Could not register toshiba backlight device\n"); + dev->backlight_dev = NULL; goto error; + } + dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev); /* Register rfkill switch for Bluetooth */ if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) { diff --git a/trunk/drivers/platform/x86/xo1-rfkill.c b/trunk/drivers/platform/x86/xo1-rfkill.c index b57ad8641480..41781ed8301c 100644 --- a/trunk/drivers/platform/x86/xo1-rfkill.c +++ b/trunk/drivers/platform/x86/xo1-rfkill.c @@ -15,26 +15,15 @@ #include -static bool card_blocked; - static int rfkill_set_block(void *data, bool blocked) { unsigned char cmd; - int r; - - if (blocked == card_blocked) - return 0; - if (blocked) cmd = EC_WLAN_ENTER_RESET; else cmd = EC_WLAN_LEAVE_RESET; - r = olpc_ec_cmd(cmd, NULL, 0, NULL, 0); - if (r == 0) - card_blocked = blocked; - - return r; + return olpc_ec_cmd(cmd, NULL, 0, NULL, 0); } static const struct rfkill_ops rfkill_ops = { diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 0217f7415ef5..a290be51a1f4 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -2210,7 +2210,7 @@ config FB_XILINX config FB_COBALT tristate "Cobalt server LCD frame buffer support" - depends on FB && (MIPS_COBALT || MIPS_SEAD3) + depends on FB && MIPS_COBALT config FB_SH7760 bool "SH7760/SH7763/SH7720/SH7721 LCDC support" @@ -2382,39 +2382,6 @@ config FB_BROADSHEET and could also have been called by other names when coupled with a bridge adapter. -config FB_AUO_K190X - tristate "AUO-K190X EPD controller support" - depends on FB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - help - Provides support for epaper controllers from the K190X series - of AUO. These controllers can be used to drive epaper displays - from Sipix. - - This option enables the common support, shared by the individual - controller drivers. You will also have to enable the driver - for the controller type used in your device. - -config FB_AUO_K1900 - tristate "AUO-K1900 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1900 epd-controller. - This controller can drive Sipix epaper displays but can only do - serial updates, reducing the number of possible frames per second. - -config FB_AUO_K1901 - tristate "AUO-K1901 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1901 epd-controller. - This controller can drive Sipix epaper displays and supports - concurrent updates, making higher frames per second possible. - config FB_JZ4740 tristate "JZ4740 LCD framebuffer support" depends on FB && MACH_JZ4740 diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index ee8dafb69e36..9356add945b3 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -118,9 +118,6 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o obj-$(CONFIG_FB_METRONOME) += metronomefb.o obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o -obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o -obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o -obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_SH7760) += sh7760fb.o obj-$(CONFIG_FB_IMX) += imxfb.o diff --git a/trunk/drivers/video/auo_k1900fb.c b/trunk/drivers/video/auo_k1900fb.c deleted file mode 100644 index c36cf961dcb2..000000000000 --- a/trunk/drivers/video/auo_k1900fb.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * auok190xfb.c -- FB driver for AUO-K1900 controllers - * - * Copyright (C) 2011, 2012 Heiko Stuebner - * - * based on broadsheetfb.c - * - * Copyright (C) 2008, Jaya Kumar - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. - * - * This driver is written to be used with the AUO-K1900 display controller. - * - * It is intended to be architecture independent. A board specific driver - * must be used to perform all the physical IO interactions. - * - * The controller supports different update modes: - * mode0+1 16 step gray (4bit) - * mode2 4 step gray (2bit) - FIXME: add strange refresh - * mode3 2 step gray (1bit) - FIXME: add strange refresh - * mode4 handwriting mode (strange behaviour) - * mode5 automatic selection of update mode - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include