summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/video.c11
-rw-r--r--drivers/amba/tegra-ahb.c1
-rw-r--r--drivers/base/platform.c7
-rw-r--r--drivers/block/Kconfig15
-rw-r--r--drivers/block/cciss.c1
-rw-r--r--drivers/block/floppy.c90
-rw-r--r--drivers/block/loop.c17
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c19
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h3
-rw-r--r--drivers/block/xen-blkback/common.h4
-rw-r--r--drivers/block/xen-blkback/xenbus.c9
-rw-r--r--drivers/bluetooth/ath3k.c1
-rw-r--r--drivers/bluetooth/btusb.c1
-rw-r--r--drivers/bluetooth/hci_ldisc.c7
-rw-r--r--drivers/bus/omap-ocp2scp.c68
-rw-r--r--drivers/char/hw_random/omap-rng.c2
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-zynq.c383
-rw-r--r--drivers/clk/ux500/u8500_clk.c50
-rw-r--r--drivers/cpufreq/powernow-k8.c2
-rw-r--r--drivers/crypto/omap-aes.c8
-rw-r--r--drivers/crypto/omap-sham.c10
-rw-r--r--drivers/crypto/tegra-aes.c2
-rw-r--r--drivers/dma/imx-dma.c137
-rw-r--r--drivers/dma/imx-sdma.c1
-rw-r--r--drivers/dma/ipu/ipu_idmac.c3
-rw-r--r--drivers/dma/ipu/ipu_irq.c3
-rw-r--r--drivers/dma/omap-dma.c5
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/gpio-74x164.c2
-rw-r--r--drivers/gpio/gpio-mvebu.c4
-rw-r--r--drivers/gpio/gpio-omap.c35
-rw-r--r--drivers/gpio/gpio-samsung.c43
-rw-r--r--drivers/gpio/gpio-timberdale.c4
-rw-r--r--drivers/gpio/gpiolib.c10
-rw-r--r--drivers/gpu/drm/drm_fops.c44
-rw-r--r--drivers/gpu/drm/exynos/Kconfig2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c33
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c2
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c3
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c11
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c14
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c2
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c84
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo_regs.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/core/mm.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c20
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/mm.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c36
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c36
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.c16
-rw-r--r--drivers/gpu/drm/nouveau/nv04_dac.c16
-rw-r--r--drivers/gpu/drm/nouveau/nv04_dfp.c14
-rw-r--r--drivers/gpu/drm/nouveau/nv04_tv.c9
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c54
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c2
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c2
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c5
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c28
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c15
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_encoders.c175
-rw-r--r--drivers/gpu/drm/radeon/si.c1
-rw-r--r--drivers/gpu/drm/radeon/sid.h1
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc.c5
-rw-r--r--drivers/gpu/drm/ttm/ttm_tt.c4
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h2
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c12
-rw-r--r--drivers/gpu/drm/udl/udl_transfer.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c5
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c2
-rw-r--r--drivers/hid/hid-apple.c6
-rw-r--r--drivers/hid/hid-core.c6
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hid-microsoft.c18
-rw-r--r--drivers/hid/hid-multitouch.c5
-rw-r--r--drivers/hid/hidraw.c69
-rw-r--r--drivers/hwmon/asb100.c2
-rw-r--r--drivers/hwmon/fam15h_power.c4
-rw-r--r--drivers/hwmon/gpio-fan.c2
-rw-r--r--drivers/hwmon/w83627ehf.c1
-rw-r--r--drivers/hwmon/w83627hf.c2
-rw-r--r--drivers/hwmon/w83781d.c2
-rw-r--r--drivers/hwmon/w83791d.c2
-rw-r--r--drivers/hwmon/w83792d.c2
-rw-r--r--drivers/hwmon/w83l786ng.c2
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-i801.c11
-rw-r--r--drivers/i2c/busses/i2c-imx.c40
-rw-r--r--drivers/i2c/busses/i2c-mxs.c186
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c9
-rw-r--r--drivers/i2c/busses/i2c-tegra.c2
-rw-r--r--drivers/i2c/i2c-stub.c (renamed from drivers/i2c/busses/i2c-stub.c)66
-rw-r--r--drivers/i2c/muxes/i2c-mux-pinctrl.c2
-rw-r--r--drivers/input/keyboard/Kconfig1
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c3
-rw-r--r--drivers/input/misc/xen-kbdfront.c5
-rw-r--r--drivers/input/mouse/bcm5974.c21
-rw-r--r--drivers/input/tablet/wacom_sys.c2
-rw-r--r--drivers/input/tablet/wacom_wac.c3
-rw-r--r--drivers/input/touchscreen/Kconfig2
-rw-r--r--drivers/input/touchscreen/egalax_ts.c23
-rw-r--r--drivers/input/touchscreen/tsc40.c1
-rw-r--r--drivers/iommu/tegra-smmu.c4
-rw-r--r--drivers/irqchip/irq-bcm2835.c3
-rw-r--r--drivers/isdn/Kconfig2
-rw-r--r--drivers/isdn/i4l/Kconfig2
-rw-r--r--drivers/isdn/i4l/isdn_common.c4
-rw-r--r--drivers/leds/Kconfig4
-rw-r--r--drivers/leds/leds-ns2.c78
-rw-r--r--drivers/leds/ledtrig-cpu.c21
-rw-r--r--drivers/md/faulty.c5
-rw-r--r--drivers/md/raid1.c2
-rw-r--r--drivers/md/raid10.c15
-rw-r--r--drivers/media/platform/omap/omap_vout.c4
-rw-r--r--drivers/media/platform/omap/omap_vout_vrfb.c6
-rw-r--r--drivers/media/platform/omap/omap_voutdef.h2
-rw-r--r--drivers/media/platform/omap3isp/isphist.c2
-rw-r--r--drivers/media/platform/omap3isp/ispstat.h2
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c1
-rw-r--r--drivers/media/platform/soc_camera/mx2_camera.c95
-rw-r--r--drivers/media/platform/soc_camera/mx3_camera.c2
-rw-r--r--drivers/media/platform/soc_camera/omap1_camera.c3
-rw-r--r--drivers/media/rc/ir-rx51.c1
-rw-r--r--drivers/mfd/menelaus.c2
-rw-r--r--drivers/mfd/omap-usb-host.c5
-rw-r--r--drivers/mfd/omap-usb-tll.c2
-rw-r--r--drivers/mfd/omap-usb.h2
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c8
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c6
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.h2
-rw-r--r--drivers/mmc/host/dw_mmc.c62
-rw-r--r--drivers/mmc/host/mxcmmc.c33
-rw-r--r--drivers/mmc/host/omap.c35
-rw-r--r--drivers/mmc/host/omap_hsmmc.c23
-rw-r--r--drivers/mmc/host/sdhci-dove.c38
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c11
-rw-r--r--drivers/mmc/host/sdhci-pci.c2
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c7
-rw-r--r--drivers/mmc/host/sdhci-s3c.c30
-rw-r--r--drivers/mmc/host/sdhci.c44
-rw-r--r--drivers/mmc/host/sdhci.h1
-rw-r--r--drivers/mmc/host/sh_mmcif.c2
-rw-r--r--drivers/mtd/nand/mxc_nand.c96
-rw-r--r--drivers/mtd/nand/omap2.c129
-rw-r--r--drivers/mtd/onenand/omap2.c47
-rw-r--r--drivers/net/bonding/bond_sysfs.c4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c162
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c13
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c10
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c6
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c3
-rw-r--r--drivers/net/ethernet/jme.c36
-rw-r--r--drivers/net/ethernet/marvell/skge.c2
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c20
-rw-r--r--drivers/net/ethernet/nxp/lpc_eth.c1
-rw-r--r--drivers/net/ethernet/realtek/r8169.c5
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c17
-rw-r--r--drivers/net/ethernet/tile/tilegx.c2
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c14
-rw-r--r--drivers/net/usb/cdc_eem.c3
-rw-r--r--drivers/net/usb/cdc_ncm.c22
-rw-r--r--drivers/net/usb/smsc95xx.c5
-rw-r--r--drivers/net/usb/usbnet.c8
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c65
-rw-r--r--drivers/net/vxlan.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c10
-rw-r--r--drivers/net/wireless/b43legacy/pio.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c23
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c2
-rw-r--r--drivers/pci/bus.c3
-rw-r--r--drivers/pci/pci-driver.c12
-rw-r--r--drivers/pci/pci-sysfs.c34
-rw-r--r--drivers/pci/pci.c32
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c20
-rw-r--r--drivers/pci/pcie/portdrv_core.c3
-rw-r--r--drivers/pci/proc.c8
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/pinctrl/Kconfig24
-rw-r--r--drivers/pinctrl/Makefile6
-rw-r--r--drivers/pinctrl/core.c2
-rw-r--r--drivers/pinctrl/core.h2
-rw-r--r--drivers/pinctrl/mvebu/Kconfig24
-rw-r--r--drivers/pinctrl/mvebu/Makefile5
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-370.c (renamed from drivers/pinctrl/pinctrl-armada-370.c)0
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-xp.c (renamed from drivers/pinctrl/pinctrl-armada-xp.c)0
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-dove.c (renamed from drivers/pinctrl/pinctrl-dove.c)22
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-kirkwood.c484
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c (renamed from drivers/pinctrl/pinctrl-mvebu.c)1
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.h (renamed from drivers/pinctrl/pinctrl-mvebu.h)0
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c477
-rw-r--r--drivers/pinctrl/pinctrl-exynos.h170
-rw-r--r--drivers/pinctrl/pinctrl-kirkwood.c472
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c205
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h30
-rw-r--r--drivers/pinctrl/pinmux.c67
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c2
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear1310.c365
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear1340.c41
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear320.c8
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear3xx.h1
-rw-r--r--drivers/power/Kconfig3
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/reset/Kconfig15
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/gpio-poweroff.c129
-rw-r--r--drivers/rapidio/rio.c2
-rw-r--r--drivers/regulator/core.c33
-rw-r--r--drivers/rtc/rtc-mxc.c34
-rw-r--r--drivers/s390/char/con3215.c12
-rw-r--r--drivers/s390/cio/css.h3
-rw-r--r--drivers/s390/cio/device.c8
-rw-r--r--drivers/s390/cio/idset.c3
-rw-r--r--drivers/s390/net/qeth_core_main.c24
-rw-r--r--drivers/s390/net/qeth_l2_main.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c25
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h1
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c77
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.h2
-rw-r--r--drivers/scsi/qlogicpti.c13
-rw-r--r--drivers/staging/android/android_alarm.h4
-rw-r--r--drivers/staging/nvec/nvec.c1
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/host_os.h1
-rw-r--r--drivers/target/iscsi/iscsi_target.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h1
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c1
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c22
-rw-r--r--drivers/target/iscsi/iscsi_target_util.h1
-rw-r--r--drivers/target/target_core_configfs.c3
-rw-r--r--drivers/target/target_core_device.c18
-rw-r--r--drivers/target/target_core_sbc.c18
-rw-r--r--drivers/target/target_core_spc.c2
-rw-r--r--drivers/target/target_core_tmr.c6
-rw-r--r--drivers/target/target_core_transport.c1
-rw-r--r--drivers/thermal/exynos_thermal.c2
-rw-r--r--drivers/thermal/rcar_thermal.c2
-rw-r--r--drivers/tty/hvc/hvc_console.c7
-rw-r--r--drivers/tty/n_tty.c752
-rw-r--r--drivers/tty/pty.c30
-rw-r--r--drivers/tty/serial/8250/8250.c9
-rw-r--r--drivers/tty/serial/8250/8250.h36
-rw-r--r--drivers/tty/serial/8250/8250_early.c2
-rw-r--r--drivers/tty/serial/max310x.c1
-rw-r--r--drivers/tty/serial/samsung.c16
-rw-r--r--drivers/tty/tty_audit.c15
-rw-r--r--drivers/tty/tty_buffer.c228
-rw-r--r--drivers/tty/tty_io.c15
-rw-r--r--drivers/tty/tty_ldisc.c15
-rw-r--r--drivers/tty/tty_port.c2
-rw-r--r--drivers/tty/vt/selection.c9
-rw-r--r--drivers/uio/Kconfig1
-rw-r--r--drivers/uio/uio_pruss.c24
-rw-r--r--drivers/usb/core/hcd.c16
-rw-r--r--drivers/usb/early/ehci-dbgp.c15
-rw-r--r--drivers/usb/gadget/omap_udc.c4
-rw-r--r--drivers/usb/gadget/u_ether.c3
-rw-r--r--drivers/usb/host/ehci-ls1x.c2
-rw-r--r--drivers/usb/host/ehci-mxc.c1
-rw-r--r--drivers/usb/host/ehci-omap.c3
-rw-r--r--drivers/usb/host/ehci-orion.c38
-rw-r--r--drivers/usb/host/ehci-tegra.c5
-rw-r--r--drivers/usb/host/ohci-omap.c5
-rw-r--r--drivers/usb/host/ohci-omap3.c1
-rw-r--r--drivers/usb/host/ohci-xls.c2
-rw-r--r--drivers/usb/musb/am35x.c3
-rw-r--r--drivers/usb/musb/musb_dsps.c3
-rw-r--r--drivers/usb/musb/musb_gadget.c30
-rw-r--r--drivers/usb/musb/omap2430.h2
-rw-r--r--drivers/usb/musb/tusb6010_omap.c9
-rw-r--r--drivers/usb/musb/ux500.c2
-rw-r--r--drivers/usb/otg/Kconfig4
-rw-r--r--drivers/usb/phy/tegra_usb_phy.c4
-rw-r--r--drivers/usb/serial/keyspan.c3
-rw-r--r--drivers/usb/serial/option.c9
-rw-r--r--drivers/usb/serial/usb_wwan.c10
-rw-r--r--drivers/video/imxfb.c38
-rw-r--r--drivers/video/mx3fb.c3
-rw-r--r--drivers/video/omap/lcd_inn1510.c7
-rw-r--r--drivers/video/omap/lcdc.c2
-rw-r--r--drivers/video/omap/omapfb_main.c2
-rw-r--r--drivers/video/omap/sossi.c2
-rw-r--r--drivers/video/omap2/dss/core.c2
-rw-r--r--drivers/video/omap2/dss/dispc.c43
-rw-r--r--drivers/video/omap2/dss/dss.c39
-rw-r--r--drivers/video/omap2/dss/dss_features.c64
-rw-r--r--drivers/video/omap2/dss/dss_features.h5
-rw-r--r--drivers/video/omap2/dss/hdmi.c3
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c8
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c2
-rw-r--r--drivers/video/omap2/vrfb.c142
-rw-r--r--drivers/video/xen-fbfront.c5
-rw-r--r--drivers/virtio/virtio.c4
-rw-r--r--drivers/watchdog/at91sam9_wdt.c11
-rw-r--r--drivers/watchdog/imx2_wdt.c1
-rw-r--r--drivers/watchdog/omap_wdt.c26
-rw-r--r--drivers/xen/Makefile1
-rw-r--r--drivers/xen/events.c2
-rw-r--r--drivers/xen/fallback.c80
-rw-r--r--drivers/xen/gntdev.c36
-rw-r--r--drivers/xen/xenbus/xenbus_dev_frontend.c2
321 files changed, 5424 insertions, 2942 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index f94d4c818fc..0230cb6cbb3 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1345,12 +1345,15 @@ static int
acpi_video_bus_get_devices(struct acpi_video_bus *video,
struct acpi_device *device)
{
- int status;
+ int status = 0;
struct acpi_device *dev;
- status = acpi_video_device_enumerate(video);
- if (status)
- return status;
+ /*
+ * There are systems where video module known to work fine regardless
+ * of broken _DOD and ignoring returned value here doesn't cause
+ * any issues later.
+ */
+ acpi_video_device_enumerate(video);
list_for_each_entry(dev, &device->children, node) {
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
index 0b6f0b28a48..bd5de08ad6f 100644
--- a/drivers/amba/tegra-ahb.c
+++ b/drivers/amba/tegra-ahb.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/tegra-ahb.h>
#define DRV_NAME "tegra-ahb"
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 8727e9c5eea..72c776f2a1f 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource);
*/
int platform_get_irq(struct platform_device *dev, unsigned int num)
{
+#ifdef CONFIG_SPARC
+ /* sparc does not have irqs represented as IORESOURCE_IRQ resources */
+ if (!dev || num >= dev->archdata.num_irqs)
+ return -ENXIO;
+ return dev->archdata.irqs[num];
+#else
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
return r ? r->start : -ENXIO;
+#endif
}
EXPORT_SYMBOL_GPL(platform_get_irq);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index f529407db93..824e09c4d0d 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -131,6 +131,7 @@ config BLK_CPQ_DA
config BLK_CPQ_CISS_DA
tristate "Compaq Smart Array 5xxx support"
depends on PCI
+ select CHECK_SIGNATURE
help
This is the driver for Compaq Smart Array 5xxx controllers.
Everyone using these boards should say Y here.
@@ -166,8 +167,8 @@ config BLK_DEV_DAC960
module will be called DAC960.
config BLK_DEV_UMEM
- tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL
+ tristate "Micro Memory MM5415 Battery Backed RAM support"
+ depends on PCI
---help---
Saying Y here will include support for the MM5415 family of
battery backed (Non-volatile) RAM cards.
@@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
a disc is opened for writing.
config CDROM_PKTCDVD_WCACHE
- bool "Enable write caching (EXPERIMENTAL)"
- depends on CDROM_PKTCDVD && EXPERIMENTAL
+ bool "Enable write caching"
+ depends on CDROM_PKTCDVD
help
If enabled, write caching will be set for the CD-R/W device. For now
this option is dangerous unless the CD-RW media is known good, as we
@@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
config VIRTIO_BLK
- tristate "Virtio block driver (EXPERIMENTAL)"
- depends on EXPERIMENTAL && VIRTIO
+ tristate "Virtio block driver"
+ depends on VIRTIO
---help---
This is the virtual block driver for virtio. It can be used with
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
@@ -528,7 +529,7 @@ config BLK_DEV_HD
config BLK_DEV_RBD
tristate "Rados block device (RBD)"
- depends on INET && EXPERIMENTAL && BLOCK
+ depends on INET && BLOCK
select CEPH_LIB
select LIBCRC32C
select CRYPTO_AES
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index b0f553b26d0..ca83f96756a 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
return;
}
/* write all data in the battery backed cache to disk */
- memset(flush_buf, 0, 4);
return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
4, 0, CTLR_LUNID, TYPE_CMD);
kfree(flush_buf);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 17c675c5229..1c49d717396 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
static struct platform_device floppy_device[N_DRIVE];
+static bool floppy_available(int drive)
+{
+ if (!(allowed_drive_mask & (1 << drive)))
+ return false;
+ if (fdc_state[FDC(drive)].version == FDC_NONE)
+ return false;
+ return true;
+}
+
static struct kobject *floppy_find(dev_t dev, int *part, void *data)
{
int drive = (*part & 3) | ((*part & 0x80) >> 5);
- if (drive >= N_DRIVE ||
- !(allowed_drive_mask & (1 << drive)) ||
- fdc_state[FDC(drive)].version == FDC_NONE)
+ if (drive >= N_DRIVE || !floppy_available(drive))
return NULL;
if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
return NULL;
@@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
static int __init do_floppy_init(void)
{
- int i, unit, drive;
- int err, dr;
+ int i, unit, drive, err;
set_debugt();
interruptjiffies = resultjiffies = jiffies;
@@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
raw_cmd = NULL;
- for (dr = 0; dr < N_DRIVE; dr++) {
- disks[dr] = alloc_disk(1);
- if (!disks[dr]) {
- err = -ENOMEM;
- goto out_put_disk;
- }
+ floppy_wq = alloc_ordered_workqueue("floppy", 0);
+ if (!floppy_wq)
+ return -ENOMEM;
- floppy_wq = alloc_ordered_workqueue("floppy", 0);
- if (!floppy_wq) {
+ for (drive = 0; drive < N_DRIVE; drive++) {
+ disks[drive] = alloc_disk(1);
+ if (!disks[drive]) {
err = -ENOMEM;
goto out_put_disk;
}
- disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
- if (!disks[dr]->queue) {
+ disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+ if (!disks[drive]->queue) {
err = -ENOMEM;
- goto out_destroy_workq;
+ goto out_put_disk;
}
- blk_queue_max_hw_sectors(disks[dr]->queue, 64);
- disks[dr]->major = FLOPPY_MAJOR;
- disks[dr]->first_minor = TOMINOR(dr);
- disks[dr]->fops = &floppy_fops;
- sprintf(disks[dr]->disk_name, "fd%d", dr);
+ blk_queue_max_hw_sectors(disks[drive]->queue, 64);
+ disks[drive]->major = FLOPPY_MAJOR;
+ disks[drive]->first_minor = TOMINOR(drive);
+ disks[drive]->fops = &floppy_fops;
+ sprintf(disks[drive]->disk_name, "fd%d", drive);
- init_timer(&motor_off_timer[dr]);
- motor_off_timer[dr].data = dr;
- motor_off_timer[dr].function = motor_off_callback;
+ init_timer(&motor_off_timer[drive]);
+ motor_off_timer[drive].data = drive;
+ motor_off_timer[drive].function = motor_off_callback;
}
err = register_blkdev(FLOPPY_MAJOR, "fd");
@@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
}
for (drive = 0; drive < N_DRIVE; drive++) {
- if (!(allowed_drive_mask & (1 << drive)))
- continue;
- if (fdc_state[FDC(drive)].version == FDC_NONE)
+ if (!floppy_available(drive))
continue;
floppy_device[drive].name = floppy_device_name;
@@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)
err = platform_device_register(&floppy_device[drive]);
if (err)
- goto out_release_dma;
+ goto out_remove_drives;
err = device_create_file(&floppy_device[drive].dev,
&dev_attr_cmos);
@@ -4311,29 +4313,34 @@ static int __init do_floppy_init(void)
out_unreg_platform_dev:
platform_device_unregister(&floppy_device[drive]);
+out_remove_drives:
+ while (drive--) {
+ if (floppy_available(drive)) {
+ del_gendisk(disks[drive]);
+ device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+ platform_device_unregister(&floppy_device[drive]);
+ }
+ }
out_release_dma:
if (atomic_read(&usage_count))
floppy_release_irq_and_dma();
out_unreg_region:
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
platform_driver_unregister(&floppy_driver);
-out_destroy_workq:
- destroy_workqueue(floppy_wq);
out_unreg_blkdev:
unregister_blkdev(FLOPPY_MAJOR, "fd");
out_put_disk:
- while (dr--) {
- del_timer_sync(&motor_off_timer[dr]);
- if (disks[dr]->queue) {
- blk_cleanup_queue(disks[dr]->queue);
- /*
- * put_disk() is not paired with add_disk() and
- * will put queue reference one extra time. fix it.
- */
- disks[dr]->queue = NULL;
+ for (drive = 0; drive < N_DRIVE; drive++) {
+ if (!disks[drive])
+ break;
+ if (disks[drive]->queue) {
+ del_timer_sync(&motor_off_timer[drive]);
+ blk_cleanup_queue(disks[drive]->queue);
+ disks[drive]->queue = NULL;
}
- put_disk(disks[dr]);
+ put_disk(disks[drive]);
}
+ destroy_workqueue(floppy_wq);
return err;
}
@@ -4551,8 +4558,7 @@ static void __exit floppy_module_exit(void)
for (drive = 0; drive < N_DRIVE; drive++) {
del_timer_sync(&motor_off_timer[drive]);
- if ((allowed_drive_mask & (1 << drive)) &&
- fdc_state[FDC(drive)].version != FDC_NONE) {
+ if (floppy_available(drive)) {
del_gendisk(disks[drive]);
device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
platform_device_unregister(&floppy_device[drive]);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index e9d594fd12c..54046e51160 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
if (lo->lo_state != Lo_bound)
return -ENXIO;
- if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */
- return -EBUSY;
+ /*
+ * If we've explicitly asked to tear down the loop device,
+ * and it has an elevated reference count, set it for auto-teardown when
+ * the last reference goes away. This stops $!~#$@ udev from
+ * preventing teardown because it decided that it needs to run blkid on
+ * the loopback device whenever they appear. xfstests is notorious for
+ * failing tests because blkid via udev races with a losetup
+ * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
+ * command to fail with EBUSY.
+ */
+ if (lo->lo_refcnt > 1) {
+ lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
+ mutex_unlock(&lo->lo_ctl_mutex);
+ return 0;
+ }
if (filp == NULL)
return -EINVAL;
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index f946d31d691..adc6f36564c 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,
}
return rv;
}
-
-static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
+static void mtip_set_timeout(struct driver_data *dd,
+ struct host_to_dev_fis *fis,
+ unsigned int *timeout, u8 erasemode)
{
switch (fis->command) {
case ATA_CMD_DOWNLOAD_MICRO:
@@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
break;
case ATA_CMD_SEC_ERASE_UNIT:
case 0xFC:
- *timeout = 240000; /* 4 minutes */
+ if (erasemode)
+ *timeout = ((*(dd->port->identify + 90) * 2) * 60000);
+ else
+ *timeout = ((*(dd->port->identify + 89) * 2) * 60000);
break;
case ATA_CMD_STANDBYNOW1:
*timeout = 120000; /* 2 minutes */
@@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
unsigned int transfer_size;
unsigned long task_file_data;
int intotal = outtotal + req_task->out_size;
+ int erasemode = 0;
taskout = req_task->out_size;
taskin = req_task->in_size;
@@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
fis.lba_hi,
fis.device);
- mtip_set_timeout(&fis, &timeout);
+ /* check for erase mode support during secure erase.*/
+ if ((fis.command == ATA_CMD_SEC_ERASE_UNIT)
+ && (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+ erasemode = 1;
+ }
+
+ mtip_set_timeout(dd, &fis, &timeout, erasemode);
/* Determine the correct transfer size.*/
if (force_single_sector)
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 18627a1d04c..5f4a917bd8b 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -33,6 +33,9 @@
/* offset of Device Control register in PCIe extended capabilites space */
#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48
+/* check for erase mode support during secure erase */
+#define MTIP_SEC_ERASE_MODE 0x3
+
/* # of times to retry timed out/failed IOs */
#define MTIP_MAX_RETRIES 2
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 9ad3b5ec1dc..9a54623e52d 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -158,8 +158,8 @@ struct xen_vbd {
struct block_device *bdev;
/* Cached size parameter. */
sector_t size;
- bool flush_support;
- bool discard_secure;
+ unsigned int flush_support:1;
+ unsigned int discard_secure:1;
};
struct backend_info;
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 4f66171c668..f58434c2617 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
{
struct xen_blkif *blkif;
- blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
+ blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
if (!blkif)
return ERR_PTR(-ENOMEM);
- memset(blkif, 0, sizeof(*blkif));
blkif->domid = domid;
spin_lock_init(&blkif->blk_ring_lock);
atomic_set(&blkif->refcnt, 1);
@@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
}
}
-void xen_blkif_free(struct xen_blkif *blkif)
+static void xen_blkif_free(struct xen_blkif *blkif)
{
if (!atomic_dec_and_test(&blkif->refcnt))
BUG();
@@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
VBD_SHOW(mode, "%s\n", be->mode);
-int xenvbd_sysfs_addif(struct xenbus_device *dev)
+static int xenvbd_sysfs_addif(struct xenbus_device *dev)
{
int error;
@@ -281,7 +280,7 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device);
return error;
}
-void xenvbd_sysfs_delif(struct xenbus_device *dev)
+static void xenvbd_sysfs_delif(struct xenbus_device *dev)
{
sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
device_remove_file(&dev->dev, &dev_attr_mode);
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index fc2de5528dc..b00000e8aef 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -67,6 +67,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x13d3, 0x3304) },
{ USB_DEVICE(0x0930, 0x0215) },
{ USB_DEVICE(0x0489, 0xE03D) },
+ { USB_DEVICE(0x0489, 0xE027) },
/* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE(0x03F0, 0x311D) },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index debda27df9b..ee82f2fb65f 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -124,6 +124,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
/* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index c8abce3d2d9..ed0fade46ae 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -270,15 +270,10 @@ static int hci_uart_send_frame(struct sk_buff *skb)
*/
static int hci_uart_tty_open(struct tty_struct *tty)
{
- struct hci_uart *hu = (void *) tty->disc_data;
+ struct hci_uart *hu;
BT_DBG("tty %p", tty);
- /* FIXME: This btw is bogus, nothing requires the old ldisc to clear
- the pointer */
- if (hu)
- return -EEXIST;
-
/* Error if the tty has no write op instead of leaving an exploitable
hole */
if (tty->ops->write == NULL)
diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c
index ff63560b846..0c48b0e05ed 100644
--- a/drivers/bus/omap-ocp2scp.c
+++ b/drivers/bus/omap-ocp2scp.c
@@ -22,6 +22,26 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/platform_data/omap_ocp2scp.h>
+
+/**
+ * _count_resources - count for the number of resources
+ * @res: struct resource *
+ *
+ * Count and return the number of resources populated for the device that is
+ * connected to ocp2scp.
+ */
+static unsigned _count_resources(struct resource *res)
+{
+ int cnt = 0;
+
+ while (res->start != res->end) {
+ cnt++;
+ res++;
+ }
+
+ return cnt;
+}
static int ocp2scp_remove_devices(struct device *dev, void *c)
{
@@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
{
- int ret;
- struct device_node *np = pdev->dev.of_node;
+ int ret;
+ unsigned res_cnt, i;
+ struct device_node *np = pdev->dev.of_node;
+ struct platform_device *pdev_child;
+ struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data;
+ struct omap_ocp2scp_dev *dev;
if (np) {
ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
if (ret) {
- dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n");
+ dev_err(&pdev->dev,
+ "failed to add resources for ocp2scp child\n");
goto err0;
}
+ } else if (pdata) {
+ for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++,
+ dev++) {
+ res_cnt = _count_resources(dev->res);
+
+ pdev_child = platform_device_alloc(dev->drv_name,
+ PLATFORM_DEVID_AUTO);
+ if (!pdev_child) {
+ dev_err(&pdev->dev,
+ "failed to allocate mem for ocp2scp child\n");
+ goto err0;
+ }
+
+ ret = platform_device_add_resources(pdev_child,
+ dev->res, res_cnt);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to add resources for ocp2scp child\n");
+ goto err1;
+ }
+
+ pdev_child->dev.parent = &pdev->dev;
+
+ ret = platform_device_add(pdev_child);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to register ocp2scp child device\n");
+ goto err1;
+ }
+ }
+ } else {
+ dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n");
+ return -EINVAL;
}
+
pm_runtime_enable(&pdev->dev);
return 0;
+err1:
+ platform_device_put(pdev_child);
+
err0:
device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index a5effd813ab..45e467dcc8c 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -27,8 +27,6 @@
#include <asm/io.h>
-#include <plat/cpu.h>
-
#define RNG_OUT_REG 0x00 /* Output register */
#define RNG_STAT_REG 0x04 /* Status register
[0] = STAT_BUSY */
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b91de0..d35a34c5836 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -19,6 +19,7 @@ endif
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
+obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o
# Chip specific
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c
new file mode 100644
index 00000000000..37a30514fd6
--- /dev/null
+++ b/drivers/clk/clk-zynq.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright <josh.cartwright@ni.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+
+static void __iomem *slcr_base;
+
+struct zynq_pll_clk {
+ struct clk_hw hw;
+ void __iomem *pll_ctrl;
+ void __iomem *pll_cfg;
+};
+
+#define to_zynq_pll_clk(hw) container_of(hw, struct zynq_pll_clk, hw)
+
+#define CTRL_PLL_FDIV(x) ((x) >> 12)
+
+static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
+ return parent_rate * CTRL_PLL_FDIV(ioread32(pll->pll_ctrl));
+}
+
+static const struct clk_ops zynq_pll_clk_ops = {
+ .recalc_rate = zynq_pll_recalc_rate,
+};
+
+static void __init zynq_pll_clk_setup(struct device_node *np)
+{
+ struct clk_init_data init;
+ struct zynq_pll_clk *pll;
+ const char *parent_name;
+ struct clk *clk;
+ u32 regs[2];
+ int ret;
+
+ ret = of_property_read_u32_array(np, "reg", regs, ARRAY_SIZE(regs));
+ if (WARN_ON(ret))
+ return;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (WARN_ON(!pll))
+ return;
+
+ pll->pll_ctrl = slcr_base + regs[0];
+ pll->pll_cfg = slcr_base + regs[1];
+
+ of_property_read_string(np, "clock-output-names", &init.name);
+
+ init.ops = &zynq_pll_clk_ops;
+ parent_name = of_clk_get_parent_name(np, 0);
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(ret))
+ return;
+}
+
+struct zynq_periph_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *gates[2];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_periph_clk(hw) container_of(hw, struct zynq_periph_clk, hw)
+
+static const u8 periph_clk_parent_map[] = {
+ 0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return parent_rate / PERIPH_CLK_CTRL_DIV(ioread32(periph->clk_ctrl));
+}
+
+static u8 zynq_periph_get_parent(struct clk_hw *hw)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
+ return PERIPH_CLK_CTRL_SRC(ioread32(periph->clk_ctrl));
+}
+
+static const struct clk_ops zynq_periph_clk_ops = {
+ .recalc_rate = zynq_periph_recalc_rate,
+ .get_parent = zynq_periph_get_parent,
+};
+
+static void __init zynq_periph_clk_setup(struct device_node *np)
+{
+ struct zynq_periph_clk *periph;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ int clk_num = 0, err;
+ const char *name;
+ struct clk *clk;
+ u32 reg;
+ int i;
+
+ err = of_property_read_u32(np, "reg", &reg);
+ if (WARN_ON(err))
+ return;
+
+ periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+ if (WARN_ON(!periph))
+ return;
+
+ periph->clk_ctrl = slcr_base + reg;
+ spin_lock_init(&periph->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_periph_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ periph->hw.init = &init;
+
+ clk = clk_register(NULL, &periph->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(err))
+ return;
+
+ err = of_property_read_string_index(np, "clock-output-names", 0,
+ &name);
+ if (WARN_ON(err))
+ return;
+
+ periph->gates[0] = clk_register_gate(NULL, name, np->name, 0,
+ periph->clk_ctrl, 0, 0,
+ &periph->clkact_lock);
+ if (WARN_ON(IS_ERR(periph->gates[0])))
+ return;
+ clk_num++;
+
+ /* some periph clks have 2 downstream gates */
+ err = of_property_read_string_index(np, "clock-output-names", 1,
+ &name);
+ if (err != -ENODATA) {
+ periph->gates[1] = clk_register_gate(NULL, name, np->name, 0,
+ periph->clk_ctrl, 1, 0,
+ &periph->clkact_lock);
+ if (WARN_ON(IS_ERR(periph->gates[1])))
+ return;
+ clk_num++;
+ }
+
+ periph->onecell_data.clks = periph->gates;
+ periph->onecell_data.clk_num = clk_num;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &periph->onecell_data);
+ if (WARN_ON(err))
+ return;
+}
+
+/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
+ * derivative rates depend on CLK_621_TRUE
+ */
+
+struct zynq_cpu_clk {
+ struct clk_hw hw;
+ struct clk_onecell_data onecell_data;
+ struct clk *subclks[4];
+ void __iomem *clk_ctrl;
+ spinlock_t clkact_lock;
+};
+
+#define to_zynq_cpu_clk(hw) container_of(hw, struct zynq_cpu_clk, hw)
+
+static const u8 zynq_cpu_clk_parent_map[] = {
+ 1, 1, 2, 0
+};
+#define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
+#define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static u8 zynq_cpu_clk_get_parent(struct clk_hw *hw)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return CPU_CLK_SRCSEL(ioread32(cpuclk->clk_ctrl));
+}
+
+static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
+ return parent_rate / CPU_CLK_CTRL_DIV(ioread32(cpuclk->clk_ctrl));
+}
+
+static const struct clk_ops zynq_cpu_clk_ops = {
+ .get_parent = zynq_cpu_clk_get_parent,
+ .recalc_rate = zynq_cpu_clk_recalc_rate,
+};
+
+struct zynq_cpu_subclk {
+ struct clk_hw hw;
+ void __iomem *clk_621;
+ enum {
+ CPU_SUBCLK_6X4X,
+ CPU_SUBCLK_3X2X,
+ CPU_SUBCLK_2X,
+ CPU_SUBCLK_1X,
+ } which;
+};
+
+#define CLK_621_TRUE(x) ((x) & 1)
+
+#define to_zynq_cpu_subclk(hw) container_of(hw, struct zynq_cpu_subclk, hw);
+
+static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long uninitialized_var(rate);
+ struct zynq_cpu_subclk *subclk;
+ bool is_621;
+
+ subclk = to_zynq_cpu_subclk(hw)
+ is_621 = CLK_621_TRUE(ioread32(subclk->clk_621));
+
+ switch (subclk->which) {
+ case CPU_SUBCLK_6X4X:
+ rate = parent_rate;
+ break;
+ case CPU_SUBCLK_3X2X:
+ rate = parent_rate / 2;
+ break;
+ case CPU_SUBCLK_2X:
+ rate = parent_rate / (is_621 ? 3 : 2);
+ break;
+ case CPU_SUBCLK_1X:
+ rate = parent_rate / (is_621 ? 6 : 4);
+ break;
+ };
+
+ return rate;
+}
+
+static const struct clk_ops zynq_cpu_subclk_ops = {
+ .recalc_rate = zynq_cpu_subclk_recalc_rate,
+};
+
+static struct clk *zynq_cpu_subclk_setup(struct device_node *np, u8 which,
+ void __iomem *clk_621)
+{
+ struct zynq_cpu_subclk *subclk;
+ struct clk_init_data init;
+ struct clk *clk;
+ int err;
+
+ err = of_property_read_string_index(np, "clock-output-names",
+ which, &init.name);
+ if (WARN_ON(err))
+ goto err_read_output_name;
+
+ subclk = kzalloc(sizeof(*subclk), GFP_KERNEL);
+ if (!subclk)
+ goto err_subclk_alloc;
+
+ subclk->clk_621 = clk_621;
+ subclk->which = which;
+
+ init.ops = &zynq_cpu_subclk_ops;
+ init.parent_names = &np->name;
+ init.num_parents = 1;
+
+ subclk->hw.init = &init;
+
+ clk = clk_register(NULL, &subclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ goto err_clk_register;
+
+ return clk;
+
+err_clk_register:
+ kfree(subclk);
+err_subclk_alloc:
+err_read_output_name:
+ return ERR_PTR(-EINVAL);
+}
+
+static void __init zynq_cpu_clk_setup(struct device_node *np)
+{
+ struct zynq_cpu_clk *cpuclk;
+ const char *parent_names[3];
+ struct clk_init_data init;
+ void __iomem *clk_621;
+ struct clk *clk;
+ u32 reg[2];
+ int err;
+ int i;
+
+ err = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
+ if (WARN_ON(err))
+ return;
+
+ cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+ if (WARN_ON(!cpuclk))
+ return;
+
+ cpuclk->clk_ctrl = slcr_base + reg[0];
+ clk_621 = slcr_base + reg[1];
+ spin_lock_init(&cpuclk->clkact_lock);
+
+ init.name = np->name;
+ init.ops = &zynq_cpu_clk_ops;
+ for (i = 0; i < ARRAY_SIZE(parent_names); i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+ init.parent_names = parent_names;
+ init.num_parents = ARRAY_SIZE(parent_names);
+
+ cpuclk->hw.init = &init;
+
+ clk = clk_register(NULL, &cpuclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ return;
+
+ err = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (WARN_ON(err))
+ return;
+
+ for (i = 0; i < 4; i++) {
+ cpuclk->subclks[i] = zynq_cpu_subclk_setup(np, i, clk_621);
+ if (WARN_ON(IS_ERR(cpuclk->subclks[i])))
+ return;
+ }
+
+ cpuclk->onecell_data.clks = cpuclk->subclks;
+ cpuclk->onecell_data.clk_num = i;
+
+ err = of_clk_add_provider(np, of_clk_src_onecell_get,
+ &cpuclk->onecell_data);
+ if (WARN_ON(err))
+ return;
+}
+
+static const __initconst struct of_device_id zynq_clk_match[] = {
+ { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+ { .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, },
+ { .compatible = "xlnx,zynq-periph-clock",
+ .data = zynq_periph_clk_setup, },
+ { .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, },
+ {}
+};
+
+void __init xilinx_zynq_clocks_init(void __iomem *slcr)
+{
+ slcr_base = slcr;
+ of_clk_init(zynq_clk_match);
+}
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index ca4a25ed844..e2c17d187d9 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -40,7 +40,7 @@ void u8500_clk_init(void)
CLK_IS_ROOT|CLK_IGNORE_UNUSED,
32768);
clk_register_clkdev(clk, "clk32k", NULL);
- clk_register_clkdev(clk, NULL, "rtc-pl031");
+ clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
/* PRCMU clocks */
fw_version = prcmu_get_fw_version();
@@ -228,10 +228,17 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE,
BIT(2), 0);
+ clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
+
clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE,
BIT(3), 0);
+ clk_register_clkdev(clk, "apb_pclk", "msp0");
+ clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0");
+
clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE,
BIT(4), 0);
+ clk_register_clkdev(clk, "apb_pclk", "msp1");
+ clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1");
clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE,
BIT(5), 0);
@@ -239,6 +246,7 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE,
BIT(6), 0);
+ clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE,
BIT(7), 0);
@@ -246,6 +254,7 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE,
BIT(8), 0);
+ clk_register_clkdev(clk, "apb_pclk", "slimbus0");
clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE,
BIT(9), 0);
@@ -255,11 +264,16 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE,
BIT(10), 0);
+ clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
+
clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE,
BIT(11), 0);
+ clk_register_clkdev(clk, "apb_pclk", "msp3");
+ clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3");
clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE,
BIT(0), 0);
+ clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE,
BIT(1), 0);
@@ -279,12 +293,13 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE,
BIT(5), 0);
+ clk_register_clkdev(clk, "apb_pclk", "msp2");
+ clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2");
clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE,
BIT(6), 0);
clk_register_clkdev(clk, "apb_pclk", "sdi1");
-
clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE,
BIT(7), 0);
clk_register_clkdev(clk, "apb_pclk", "sdi3");
@@ -316,10 +331,15 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
BIT(1), 0);
+ clk_register_clkdev(clk, "apb_pclk", "ssp0");
+
clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE,
BIT(2), 0);
+ clk_register_clkdev(clk, "apb_pclk", "ssp1");
+
clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE,
BIT(3), 0);
+ clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE,
BIT(4), 0);
@@ -401,10 +421,17 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "nmk-i2c.1");
+
clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "msp0");
+ clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0");
+
clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "msp1");
+ clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1");
clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE);
@@ -412,17 +439,25 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "nmk-i2c.2");
+
clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
- U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
- /* FIXME: Redefinition of BIT(3). */
+ U8500_CLKRST1_BASE, BIT(8), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "slimbus0");
+
clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "nmk-i2c.4");
+
clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "msp3");
+ clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3");
/* Periph2 */
clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "nmk-i2c.3");
clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE);
@@ -430,6 +465,8 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "msp2");
+ clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2");
clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE);
@@ -450,10 +487,15 @@ void u8500_clk_init(void)
/* Periph3 */
clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "ssp0");
+
clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "ssp1");
+
clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "nmk-i2c.0");
clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE);
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index c16a3a593ba..e3ebb4fa2c3 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -5,7 +5,7 @@
* http://www.gnu.org/licenses/gpl.html
*
* Maintainer:
- * Andreas Herrmann <andreas.herrmann3@amd.com>
+ * Andreas Herrmann <herrmann.der.user@googlemail.com>
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones on behalf of SuSE Labs
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 093a8af59cb..649a146e138 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -29,8 +29,7 @@
#include <crypto/scatterwalk.h>
#include <crypto/aes.h>
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
/* OMAP TRM gives bitfields as start:end, where start is the higher bit
number. For example 7:0 */
@@ -941,11 +940,6 @@ static int __init omap_aes_mod_init(void)
{
pr_info("loading %s driver\n", "omap-aes");
- if (!cpu_class_is_omap2() || omap_type() != OMAP2_DEVICE_TYPE_SEC) {
- pr_err("Unsupported cpu\n");
- return -ENODEV;
- }
-
return platform_driver_register(&omap_aes_driver);
}
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index a3fd6fc504b..d76fe06b941 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -37,8 +37,7 @@
#include <crypto/hash.h>
#include <crypto/internal/hash.h>
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <mach/irqs.h>
#define SHA_REG_DIGEST(x) (0x00 + ((x) * 0x04))
@@ -1289,13 +1288,6 @@ static int __init omap_sham_mod_init(void)
{
pr_info("loading %s driver\n", "omap-sham");
- if (!cpu_class_is_omap2() ||
- (omap_type() != OMAP2_DEVICE_TYPE_SEC &&
- omap_type() != OMAP2_DEVICE_TYPE_EMU)) {
- pr_err("Unsupported cpu\n");
- return -ENODEV;
- }
-
return platform_driver_register(&omap_sham_driver);
}
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
index 37185e6630c..e69f3bc473b 100644
--- a/drivers/crypto/tegra-aes.c
+++ b/drivers/crypto/tegra-aes.c
@@ -41,8 +41,6 @@
#include <linux/completion.h>
#include <linux/workqueue.h>
-#include <mach/clk.h>
-
#include <crypto/scatterwalk.h>
#include <crypto/aes.h>
#include <crypto/internal/rng.h>
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 7d9554cc497..dbf0e6f8de8 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -29,7 +29,6 @@
#include <asm/irq.h>
#include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
#include "dmaengine.h"
#define IMXDMA_MAX_CHAN_DESCRIPTORS 16
@@ -167,6 +166,12 @@ struct imxdma_channel {
int slot_2d;
};
+enum imx_dma_type {
+ IMX1_DMA,
+ IMX21_DMA,
+ IMX27_DMA,
+};
+
struct imxdma_engine {
struct device *dev;
struct device_dma_parameters dma_parms;
@@ -177,7 +182,39 @@ struct imxdma_engine {
spinlock_t lock;
struct imx_dma_2d_config slots_2d[IMX_DMA_2D_SLOTS];
struct imxdma_channel channel[IMX_DMA_CHANNELS];
+ enum imx_dma_type devtype;
+};
+
+static struct platform_device_id imx_dma_devtype[] = {
+ {
+ .name = "imx1-dma",
+ .driver_data = IMX1_DMA,
+ }, {
+ .name = "imx21-dma",
+ .driver_data = IMX21_DMA,
+ }, {
+ .name = "imx27-dma",
+ .driver_data = IMX27_DMA,
+ }, {
+ /* sentinel */
+ }
};
+MODULE_DEVICE_TABLE(platform, imx_dma_devtype);
+
+static inline int is_imx1_dma(struct imxdma_engine *imxdma)
+{
+ return imxdma->devtype == IMX1_DMA;
+}
+
+static inline int is_imx21_dma(struct imxdma_engine *imxdma)
+{
+ return imxdma->devtype == IMX21_DMA;
+}
+
+static inline int is_imx27_dma(struct imxdma_engine *imxdma)
+{
+ return imxdma->devtype == IMX27_DMA;
+}
static struct imxdma_channel *to_imxdma_chan(struct dma_chan *chan)
{
@@ -212,7 +249,9 @@ static unsigned imx_dmav1_readl(struct imxdma_engine *imxdma, unsigned offset)
static int imxdma_hw_chain(struct imxdma_channel *imxdmac)
{
- if (cpu_is_mx27())
+ struct imxdma_engine *imxdma = imxdmac->imxdma;
+
+ if (is_imx27_dma(imxdma))
return imxdmac->hw_chaining;
else
return 0;
@@ -267,7 +306,7 @@ static void imxdma_enable_hw(struct imxdma_desc *d)
imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_CCR(channel)) |
CCR_CEN | CCR_ACRPT, DMA_CCR(channel));
- if ((cpu_is_mx21() || cpu_is_mx27()) &&
+ if (!is_imx1_dma(imxdma) &&
d->sg && imxdma_hw_chain(imxdmac)) {
d->sg = sg_next(d->sg);
if (d->sg) {
@@ -436,7 +475,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
struct imxdma_engine *imxdma = dev_id;
int i, disr;
- if (cpu_is_mx21() || cpu_is_mx27())
+ if (!is_imx1_dma(imxdma))
imxdma_err_handler(irq, dev_id);
disr = imx_dmav1_readl(imxdma, DMA_DISR);
@@ -961,35 +1000,32 @@ static void imxdma_issue_pending(struct dma_chan *chan)
static int __init imxdma_probe(struct platform_device *pdev)
{
struct imxdma_engine *imxdma;
+ struct resource *res;
int ret, i;
+ int irq, irq_err;
-
- imxdma = kzalloc(sizeof(*imxdma), GFP_KERNEL);
+ imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL);
if (!imxdma)
return -ENOMEM;
- if (cpu_is_mx1()) {
- imxdma->base = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
- } else if (cpu_is_mx21()) {
- imxdma->base = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
- } else if (cpu_is_mx27()) {
- imxdma->base = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
- } else {
- kfree(imxdma);
- return 0;
- }
+ imxdma->devtype = pdev->id_entry->driver_data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ imxdma->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!imxdma->base)
+ return -EADDRNOTAVAIL;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg");
- if (IS_ERR(imxdma->dma_ipg)) {
- ret = PTR_ERR(imxdma->dma_ipg);
- goto err_clk;
- }
+ if (IS_ERR(imxdma->dma_ipg))
+ return PTR_ERR(imxdma->dma_ipg);
imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb");
- if (IS_ERR(imxdma->dma_ahb)) {
- ret = PTR_ERR(imxdma->dma_ahb);
- goto err_clk;
- }
+ if (IS_ERR(imxdma->dma_ahb))
+ return PTR_ERR(imxdma->dma_ahb);
clk_prepare_enable(imxdma->dma_ipg);
clk_prepare_enable(imxdma->dma_ahb);
@@ -997,18 +1033,25 @@ static int __init imxdma_probe(struct platform_device *pdev)
/* reset DMA module */
imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR);
- if (cpu_is_mx1()) {
- ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma);
+ if (is_imx1_dma(imxdma)) {
+ ret = devm_request_irq(&pdev->dev, irq,
+ dma_irq_handler, 0, "DMA", imxdma);
if (ret) {
dev_warn(imxdma->dev, "Can't register IRQ for DMA\n");
- goto err_enable;
+ goto err;
+ }
+
+ irq_err = platform_get_irq(pdev, 1);
+ if (irq_err < 0) {
+ ret = irq_err;
+ goto err;
}
- ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma);
+ ret = devm_request_irq(&pdev->dev, irq_err,
+ imxdma_err_handler, 0, "DMA", imxdma);
if (ret) {
dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n");
- free_irq(MX1_DMA_INT, NULL);
- goto err_enable;
+ goto err;
}
}
@@ -1038,14 +1081,14 @@ static int __init imxdma_probe(struct platform_device *pdev)
for (i = 0; i < IMX_DMA_CHANNELS; i++) {
struct imxdma_channel *imxdmac = &imxdma->channel[i];
- if (cpu_is_mx21() || cpu_is_mx27()) {
- ret = request_irq(MX2x_INT_DMACH0 + i,
+ if (!is_imx1_dma(imxdma)) {
+ ret = devm_request_irq(&pdev->dev, irq + i,
dma_irq_handler, 0, "DMA", imxdma);
if (ret) {
dev_warn(imxdma->dev, "Can't register IRQ %d "
"for DMA channel %d\n",
- MX2x_INT_DMACH0 + i, i);
- goto err_init;
+ irq + i, i);
+ goto err;
}
init_timer(&imxdmac->watchdog);
imxdmac->watchdog.function = &imxdma_watchdog;
@@ -1091,46 +1134,25 @@ static int __init imxdma_probe(struct platform_device *pdev)
ret = dma_async_device_register(&imxdma->dma_device);
if (ret) {
dev_err(&pdev->dev, "unable to register\n");
- goto err_init;
+ goto err;
}
return 0;
-err_init:
-
- if (cpu_is_mx21() || cpu_is_mx27()) {
- while (--i >= 0)
- free_irq(MX2x_INT_DMACH0 + i, NULL);
- } else if cpu_is_mx1() {
- free_irq(MX1_DMA_INT, NULL);
- free_irq(MX1_DMA_ERR, NULL);
- }
-err_enable:
+err:
clk_disable_unprepare(imxdma->dma_ipg);
clk_disable_unprepare(imxdma->dma_ahb);
-err_clk:
- kfree(imxdma);
return ret;
}
static int __exit imxdma_remove(struct platform_device *pdev)
{
struct imxdma_engine *imxdma = platform_get_drvdata(pdev);
- int i;
dma_async_device_unregister(&imxdma->dma_device);
- if (cpu_is_mx21() || cpu_is_mx27()) {
- for (i = 0; i < IMX_DMA_CHANNELS; i++)
- free_irq(MX2x_INT_DMACH0 + i, NULL);
- } else if cpu_is_mx1() {
- free_irq(MX1_DMA_INT, NULL);
- free_irq(MX1_DMA_ERR, NULL);
- }
-
clk_disable_unprepare(imxdma->dma_ipg);
clk_disable_unprepare(imxdma->dma_ahb);
- kfree(imxdma);
return 0;
}
@@ -1139,6 +1161,7 @@ static struct platform_driver imxdma_driver = {
.driver = {
.name = "imx-dma",
},
+ .id_table = imx_dma_devtype,
.remove = __exit_p(imxdma_remove),
};
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index c099ca0846f..f082aa3a918 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -40,7 +40,6 @@
#include <asm/irq.h>
#include <linux/platform_data/dma-imx-sdma.h>
#include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
#include "dmaengine.h"
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index c7573e50aa1..65855373cee 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -22,8 +22,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
#include "../dmaengine.h"
#include "ipu_intern.h"
diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c
index fa95bcc3de1..a5ee37d5320 100644
--- a/drivers/dma/ipu/ipu_irq.c
+++ b/drivers/dma/ipu/ipu_irq.c
@@ -15,8 +15,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
#include "ipu_intern.h"
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index bb2d8e7029e..7d35c237fbf 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -19,8 +19,7 @@
#include "virt-dma.h"
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
struct omap_dmadev {
struct dma_device ddev;
@@ -438,7 +437,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ);
}
- if (!cpu_class_is_omap1()) {
+ if (dma_omap2plus()) {
omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d055cee3694..6dbc4031f82 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -47,7 +47,7 @@ if GPIOLIB
config OF_GPIO
def_bool y
- depends on OF && !SPARC
+ depends on OF
config DEBUG_GPIO
bool "Debug GPIO calls"
@@ -152,7 +152,7 @@ config GPIO_MSM_V2
config GPIO_MVEBU
def_bool y
- depends on ARCH_MVEBU
+ depends on PLAT_ORION
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index ed3e55161bd..f05e54258ff 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
}
chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
- chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
+ chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
if (!chip->buffer) {
ret = -ENOMEM;
goto exit_destroy;
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 7a874129e5d..cf7afb9eb61 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
if (ret)
return ret;
+ mvebu_gpio_set(chip, pin, value);
+
spin_lock_irqsave(&mvchip->lock, flags);
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
u &= ~(1 << pin);
@@ -644,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
ct->handler = handle_edge_irq;
ct->chip.name = mvchip->chip.label;
- irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+ irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
/* Setup irq domain on top of the generic chip. */
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 94cbc842fbc..d335af1d4d8 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
}
}
+/**
+ * _clear_gpio_debounce - clear debounce settings for a gpio
+ * @bank: the gpio bank we're acting upon
+ * @gpio: the gpio number on this @gpio
+ *
+ * If a gpio is using debounce, then clear the debounce enable bit and if
+ * this is the only gpio in this bank using debounce, then clear the debounce
+ * time too. The debounce clock will also be disabled when calling this function
+ * if this is the only gpio in the bank using debounce.
+ */
+static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
+{
+ u32 gpio_bit = GPIO_BIT(bank, gpio);
+
+ if (!bank->dbck_flag)
+ return;
+
+ if (!(bank->dbck_enable_mask & gpio_bit))
+ return;
+
+ bank->dbck_enable_mask &= ~gpio_bit;
+ bank->context.debounce_en &= ~gpio_bit;
+ __raw_writel(bank->context.debounce_en,
+ bank->base + bank->regs->debounce_en);
+
+ if (!bank->dbck_enable_mask) {
+ bank->context.debounce = 0;
+ __raw_writel(bank->context.debounce, bank->base +
+ bank->regs->debounce);
+ clk_disable(bank->dbck);
+ bank->dbck_enabled = false;
+ }
+}
+
static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
unsigned trigger)
{
@@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
_set_gpio_irqenable(bank, gpio, 0);
_clear_gpio_irqstatus(bank, gpio);
_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+ _clear_gpio_debounce(bank, gpio);
}
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index a006f0db15a..88f41e51565 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2797,27 +2797,6 @@ static __init void exynos4_gpiolib_init(void)
int group = 0;
void __iomem *gpx_base;
-#ifdef CONFIG_PINCTRL_SAMSUNG
- /*
- * This gpio driver includes support for device tree support and
- * there are platforms using it. In order to maintain
- * compatibility with those platforms, and to allow non-dt
- * Exynos4210 platforms to use this gpiolib support, a check
- * is added to find out if there is a active pin-controller
- * driver support available. If it is available, this gpiolib
- * support is ignored and the gpiolib support available in
- * pin-controller driver is used. This is a temporary check and
- * will go away when all of the Exynos4210 platforms have
- * switched to using device tree and the pin-ctrl driver.
- */
- struct device_node *pctrl_np;
- const char *pctrl_compat = "samsung,pinctrl-exynos4210";
- pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat);
- if (pctrl_np)
- if (of_device_is_available(pctrl_np))
- return;
-#endif
-
/* gpio part1 */
gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
if (gpio_base1 == NULL) {
@@ -3032,6 +3011,28 @@ static __init int samsung_gpiolib_init(void)
int i, nr_chips;
int group = 0;
+#ifdef CONFIG_PINCTRL_SAMSUNG
+ /*
+ * This gpio driver includes support for device tree support and there
+ * are platforms using it. In order to maintain compatibility with those
+ * platforms, and to allow non-dt Exynos4210 platforms to use this
+ * gpiolib support, a check is added to find out if there is a active
+ * pin-controller driver support available. If it is available, this
+ * gpiolib support is ignored and the gpiolib support available in
+ * pin-controller driver is used. This is a temporary check and will go
+ * away when all of the Exynos4210 platforms have switched to using
+ * device tree and the pin-ctrl driver.
+ */
+ struct device_node *pctrl_np;
+ static const struct of_device_id exynos_pinctrl_ids[] = {
+ { .compatible = "samsung,pinctrl-exynos4210", },
+ { .compatible = "samsung,pinctrl-exynos4x12", },
+ };
+ for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
+ if (pctrl_np && of_device_is_available(pctrl_np))
+ return -ENODEV;
+#endif
+
samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
if (soc_is_s3c24xx()) {
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index 031c6adf5b6..1a3e2b9b477 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
unsigned long flags;
spin_lock_irqsave(&tgpio->lock, flags);
- tgpio->last_ier &= ~(1 << offset);
+ tgpio->last_ier &= ~(1UL << offset);
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
spin_unlock_irqrestore(&tgpio->lock, flags);
}
@@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
unsigned long flags;
spin_lock_irqsave(&tgpio->lock, flags);
- tgpio->last_ier |= 1 << offset;
+ tgpio->last_ier |= 1UL << offset;
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
spin_unlock_irqrestore(&tgpio->lock, flags);
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5d6c71edc73..1c8d9e3380e 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,
*/
status = gpio_request(gpio, "sysfs");
- if (status < 0)
+ if (status < 0) {
+ if (status == -EPROBE_DEFER)
+ status = -ENODEV;
goto done;
-
+ }
status = gpio_export(gpio, true);
if (status < 0)
gpio_free(gpio);
@@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)
spin_lock_irqsave(&gpio_lock, flags);
- if (!gpio_is_valid(gpio))
+ if (!gpio_is_valid(gpio)) {
+ status = -EINVAL;
goto done;
+ }
desc = &gpio_desc[gpio];
chip = desc->chip;
if (chip == NULL)
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 7ef1b673e1b..133b4132983 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)
int minor_id = iminor(inode);
struct drm_minor *minor;
int retcode = 0;
+ int need_setup = 0;
+ struct address_space *old_mapping;
minor = idr_find(&drm_minors_idr, minor_id);
if (!minor)
@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)
if (drm_device_is_unplugged(dev))
return -ENODEV;
+ if (!dev->open_count++)
+ need_setup = 1;
+ mutex_lock(&dev->struct_mutex);
+ old_mapping = dev->dev_mapping;
+ if (old_mapping == NULL)
+ dev->dev_mapping = &inode->i_data;
+ /* ihold ensures nobody can remove inode with our i_data */
+ ihold(container_of(dev->dev_mapping, struct inode, i_data));
+ inode->i_mapping = dev->dev_mapping;
+ filp->f_mapping = dev->dev_mapping;
+ mutex_unlock(&dev->struct_mutex);
+
retcode = drm_open_helper(inode, filp, dev);
- if (!retcode) {
- atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
- if (!dev->open_count++)
- retcode = drm_setup(dev);
- }
- if (!retcode) {
- mutex_lock(&dev->struct_mutex);
- if (dev->dev_mapping == NULL)
- dev->dev_mapping = &inode->i_data;
- /* ihold ensures nobody can remove inode with our i_data */
- ihold(container_of(dev->dev_mapping, struct inode, i_data));
- inode->i_mapping = dev->dev_mapping;
- filp->f_mapping = dev->dev_mapping;
- mutex_unlock(&dev->struct_mutex);
+ if (retcode)
+ goto err_undo;
+ atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+ if (need_setup) {
+ retcode = drm_setup(dev);
+ if (retcode)
+ goto err_undo;
}
+ return 0;
+err_undo:
+ mutex_lock(&dev->struct_mutex);
+ filp->f_mapping = old_mapping;
+ inode->i_mapping = old_mapping;
+ iput(container_of(dev->dev_mapping, struct inode, i_data));
+ dev->dev_mapping = old_mapping;
+ mutex_unlock(&dev->struct_mutex);
+ dev->open_count--;
return retcode;
}
EXPORT_SYMBOL(drm_open);
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 59a26e577b5..fc345d4ebb0 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -1,6 +1,6 @@
config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series"
- depends on DRM && PLAT_SAMSUNG
+ depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
select DRM_KMS_HELPER
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index 18c271862ca..0f68a287267 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
exynos_connector->encoder_id = encoder->base.id;
exynos_connector->manager = manager;
exynos_connector->dpms = DRM_MODE_DPMS_OFF;
+ connector->dpms = DRM_MODE_DPMS_OFF;
connector->encoder = encoder;
err = drm_mode_connector_attach_encoder(connector, encoder);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index e51503fbaf2..241ad1eeec6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -43,12 +43,14 @@
* @manager: specific encoder has its own manager to control a hardware
* appropriately and we can access a hardware drawing on this manager.
* @dpms: store the encoder dpms value.
+ * @updated: indicate whether overlay data updating is needed or not.
*/
struct exynos_drm_encoder {
struct drm_crtc *old_crtc;
struct drm_encoder drm_encoder;
struct exynos_drm_manager *manager;
- int dpms;
+ int dpms;
+ bool updated;
};
static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
@@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
switch (mode) {
case DRM_MODE_DPMS_ON:
if (manager_ops && manager_ops->apply)
- manager_ops->apply(manager->dev);
+ if (!exynos_encoder->updated)
+ manager_ops->apply(manager->dev);
+
exynos_drm_connector_power(encoder, mode);
exynos_encoder->dpms = mode;
break;
@@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
case DRM_MODE_DPMS_OFF:
exynos_drm_connector_power(encoder, mode);
exynos_encoder->dpms = mode;
+ exynos_encoder->updated = false;
break;
default:
DRM_ERROR("unspecified mode %d\n", mode);
@@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
{
- struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+ struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+ struct exynos_drm_manager *manager = exynos_encoder->manager;
struct exynos_drm_manager_ops *manager_ops = manager->ops;
DRM_DEBUG_KMS("%s\n", __FILE__);
if (manager_ops && manager_ops->commit)
manager_ops->commit(manager->dev);
+
+ /*
+ * this will avoid one issue that overlay data is updated to
+ * real hardware two times.
+ * And this variable will be used to check if the data was
+ * already updated or not by exynos_drm_encoder_dpms function.
+ */
+ exynos_encoder->updated = true;
}
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
@@ -401,19 +415,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
manager_ops->dpms(manager->dev, mode);
/*
- * set current mode to new one so that data aren't updated into
- * registers by drm_helper_connector_dpms two times.
- *
- * in case that drm_crtc_helper_set_mode() is called,
- * overlay_ops->commit() and manager_ops->commit() callbacks
- * can be called two times, first at drm_crtc_helper_set_mode()
- * and second at drm_helper_connector_dpms().
- * so with this setting, when drm_helper_connector_dpms() is called
- * encoder->funcs->dpms() will be ignored.
- */
- exynos_encoder->dpms = mode;
-
- /*
* if this condition is ok then it means that the crtc is already
* detached from encoder and last function for detaching is properly
* done, so clear pipe from manager to prevent repeated call.
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 614b2e9ac46..e7fbb823fd8 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
const struct of_device_id *match;
match = of_match_node(of_match_ptr(mixer_match_types),
pdev->dev.of_node);
- drv = match->data;
+ drv = (struct mixer_drv_data *)match->data;
} else {
drv = (struct mixer_drv_data *)
platform_get_device_id(pdev)->driver_data;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index c9bfd83dde6..61ae104dca8 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto put_gmch;
}
- i915_kick_out_firmware_fb(dev_priv);
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ i915_kick_out_firmware_fb(dev_priv);
pci_set_master(dev->pdev);
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index f78061af704..6345878ae1e 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
int old_dpms;
/* PCH platforms and VLV only support on/off. */
- if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
+ if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
if (mode == connector->dpms)
@@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
crt->base.type = INTEL_OUTPUT_ANALOG;
crt->base.cloneable = true;
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev) || IS_I830(dev))
crt->base.crtc_mask = (1 << 0);
else
crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 461a637f1ef..4154bcd7a07 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3841,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
}
}
+ if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+ /* Use VBT settings if we have an eDP panel */
+ unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+
+ if (edp_bpc < display_bpc) {
+ DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+ display_bpc = edp_bpc;
+ }
+ continue;
+ }
+
/*
* HDMI is either 12 or 8, so if the display lets 10bpc sneak
* through, clamp it down. (Note: >12bpc will be caught below.)
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 495625914e4..d7bc817f51a 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
intel_ring_emit(ring, flip_addr);
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
/* turn overlay off */
- intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
- intel_ring_emit(ring, flip_addr);
- intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+ if (IS_I830(dev)) {
+ /* Workaround: Don't disable the overlay fully, since otherwise
+ * it dies on the next OVERLAY_ON cmd. */
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_emit(ring, MI_NOOP);
+ } else {
+ intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+ intel_ring_emit(ring, flip_addr);
+ intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+ }
intel_ring_advance(ring);
return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index e019b236986..e2aacd32954 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
props.type = BACKLIGHT_RAW;
props.max_brightness = _intel_panel_get_max_backlight(dev);
if (props.max_brightness == 0) {
- DRM_ERROR("Failed to get maximum backlight value\n");
+ DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
return -ENODEV;
}
dev_priv->backlight =
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c01d97db006..c600fb06e25 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
}
#endif
+static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
+ unsigned if_index, uint8_t tx_rate,
+ uint8_t *data, unsigned length)
+{
+ uint8_t set_buf_index[2] = { if_index, 0 };
+ uint8_t hbuf_size, tmp[8];
+ int i;
+
+ if (!intel_sdvo_set_value(intel_sdvo,
+ SDVO_CMD_SET_HBUF_INDEX,
+ set_buf_index, 2))
+ return false;
+
+ if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
+ &hbuf_size, 1))
+ return false;
+
+ /* Buffer size is 0 based, hooray! */
+ hbuf_size++;
+
+ DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
+ if_index, length, hbuf_size);
+
+ for (i = 0; i < hbuf_size; i += 8) {
+ memset(tmp, 0, 8);
+ if (i < length)
+ memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
+
+ if (!intel_sdvo_set_value(intel_sdvo,
+ SDVO_CMD_SET_HBUF_DATA,
+ tmp, 8))
+ return false;
+ }
+
+ return intel_sdvo_set_value(intel_sdvo,
+ SDVO_CMD_SET_HBUF_TXRATE,
+ &tx_rate, 1);
+}
+
static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
{
struct dip_infoframe avi_if = {
@@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
.ver = DIP_VERSION_AVI,
.len = DIP_LEN_AVI,
};
- uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
- uint8_t set_buf_index[2] = { 1, 0 };
uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
- uint64_t *data = (uint64_t *)sdvo_data;
- unsigned i;
intel_dip_infoframe_csum(&avi_if);
@@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
sdvo_data[3] = avi_if.checksum;
memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
- if (!intel_sdvo_set_value(intel_sdvo,
- SDVO_CMD_SET_HBUF_INDEX,
- set_buf_index, 2))
- return false;
-
- for (i = 0; i < sizeof(sdvo_data); i += 8) {
- if (!intel_sdvo_set_value(intel_sdvo,
- SDVO_CMD_SET_HBUF_DATA,
- data, 8))
- return false;
- data++;
- }
-
- return intel_sdvo_set_value(intel_sdvo,
- SDVO_CMD_SET_HBUF_TXRATE,
- &tx_rate, 1);
+ return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
+ SDVO_HBUF_TX_VSYNC,
+ sdvo_data, sizeof(sdvo_data));
}
static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -2360,6 +2382,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
return true;
}
+static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
+{
+ struct drm_device *dev = intel_sdvo->base.base.dev;
+ struct drm_connector *connector, *tmp;
+
+ list_for_each_entry_safe(connector, tmp,
+ &dev->mode_config.connector_list, head) {
+ if (intel_attached_encoder(connector) == &intel_sdvo->base)
+ intel_sdvo_destroy(connector);
+ }
+}
+
static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
struct intel_sdvo_connector *intel_sdvo_connector,
int type)
@@ -2683,7 +2717,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
intel_sdvo->caps.output_flags) != true) {
DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
SDVO_NAME(intel_sdvo));
- goto err;
+ /* Output_setup can leave behind connectors! */
+ goto err_output;
}
/* Only enable the hotplug irq if we need it, to work around noisy
@@ -2696,12 +2731,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
/* Set the input timing to the screen. Assume always input 0. */
if (!intel_sdvo_set_target_input(intel_sdvo))
- goto err;
+ goto err_output;
if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,
&intel_sdvo->pixel_clock_min,
&intel_sdvo->pixel_clock_max))
- goto err;
+ goto err_output;
DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
"clock range %dMHz - %dMHz, "
@@ -2721,6 +2756,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
(SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
return true;
+err_output:
+ intel_sdvo_output_cleanup(intel_sdvo);
+
err:
drm_encoder_cleanup(&intel_encoder->base);
i2c_del_adapter(&intel_sdvo->ddc);
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h
index 9d030142ee4..770bdd6ecd9 100644
--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
@@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
#define SDVO_CMD_SET_AUDIO_STAT 0x91
#define SDVO_CMD_GET_AUDIO_STAT 0x92
#define SDVO_CMD_SET_HBUF_INDEX 0x93
+ #define SDVO_HBUF_INDEX_ELD 0
+ #define SDVO_HBUF_INDEX_AVI_IF 1
#define SDVO_CMD_GET_HBUF_INDEX 0x94
#define SDVO_CMD_GET_HBUF_INFO 0x95
#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96
diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c
index 4d620644867..a6d3cd6490f 100644
--- a/drivers/gpu/drm/nouveau/core/core/mm.c
+++ b/drivers/gpu/drm/nouveau/core/core/mm.c
@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node)
return -ENOMEM;
- node->offset = roundup(offset, mm->block_size);
- node->length = rounddown(offset + length, mm->block_size) - node->offset;
+
+ if (length) {
+ node->offset = roundup(offset, mm->block_size);
+ node->length = rounddown(offset + length, mm->block_size);
+ node->length -= node->offset;
+ }
list_add_tail(&node->nl_entry, &mm->nodes);
list_add_tail(&node->fl_entry, &mm->free);
mm->heap_nodes++;
- mm->heap_size += length;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 16a9afb1060..05a909a17ce 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -22,6 +22,8 @@
* Authors: Ben Skeggs
*/
+#include <subdev/bar.h>
+
#include <engine/software.h>
#include <engine/disp.h>
@@ -37,6 +39,7 @@ nv50_disp_sclass[] = {
static void
nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
{
+ struct nouveau_bar *bar = nouveau_bar(priv);
struct nouveau_disp *disp = &priv->base;
struct nouveau_software_chan *chan, *temp;
unsigned long flags;
@@ -46,18 +49,19 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
if (chan->vblank.crtc != crtc)
continue;
- nv_wr32(priv, 0x001704, chan->vblank.channel);
- nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
-
if (nv_device(priv)->chipset == 0x50) {
+ nv_wr32(priv, 0x001704, chan->vblank.channel);
+ nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
+ bar->flush(bar);
nv_wr32(priv, 0x001570, chan->vblank.offset);
nv_wr32(priv, 0x001574, chan->vblank.value);
} else {
- if (nv_device(priv)->chipset >= 0xc0) {
- nv_wr32(priv, 0x06000c,
- upper_32_bits(chan->vblank.offset));
- }
- nv_wr32(priv, 0x060010, chan->vblank.offset);
+ nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
+ bar->flush(bar);
+ nv_wr32(priv, 0x06000c,
+ upper_32_bits(chan->vblank.offset));
+ nv_wr32(priv, 0x060010,
+ lower_32_bits(chan->vblank.offset));
nv_wr32(priv, 0x060014, chan->vblank.value);
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
index 8d0021049ec..425001204a8 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
@@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent,
static int
nv40_graph_context_fini(struct nouveau_object *object, bool suspend)
{
- struct nv04_graph_priv *priv = (void *)object->engine;
- struct nv04_graph_chan *chan = (void *)object;
+ struct nv40_graph_priv *priv = (void *)object->engine;
+ struct nv40_graph_chan *chan = (void *)object;
u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4;
int ret = 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
index 12418574efe..f7c581ad199 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
@@ -38,7 +38,7 @@ struct nv40_mpeg_priv {
};
struct nv40_mpeg_chan {
- struct nouveau_mpeg base;
+ struct nouveau_mpeg_chan base;
};
/*******************************************************************************
diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h
index 9ee9bf4028c..975137ba34a 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/mm.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h
@@ -19,7 +19,6 @@ struct nouveau_mm {
u32 block_size;
int heap_nodes;
- u32 heap_size;
};
int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
index 27fb1af7a77..5f570806143 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
((priv->base.ram.size & 0x000000ff) << 32);
tags = nv_rd32(priv, 0x100320);
- if (tags) {
- ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
- if (ret)
- return ret;
+ ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
+ if (ret)
+ return ret;
- nv_debug(priv, "%d compression tags\n", tags);
- }
+ nv_debug(priv, "%d compression tags\n", tags);
size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
switch (device->chipset) {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index 3d2c88310f9..dbfc2abf0cf 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
case DCB_I2C_NVIO_BIT:
port->drive = info.drive & 0x0f;
if (device->card_type < NV_D0) {
- if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
+ if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
break;
port->drive = nv50_i2c_port[port->drive];
port->sense = port->drive;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
index 49050d991e7..9474cfca6e4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
@@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
static void
nv41_vm_flush(struct nouveau_vm *vm)
{
- struct nv04_vm_priv *priv = (void *)vm->vmm;
+ struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
mutex_lock(&nv_subdev(priv)->mutex);
nv_wr32(priv, 0x100810, 0x00000022);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 9a6e2cb282d..d3595b23434 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
* valid - it's not (rh#613284)
*/
if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
- if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
+ if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
status = connector_status_connected;
goto out;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index d2f8ffeed74..86124b131f4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
struct nouveau_display *disp;
+ u32 pclass = dev->pdev->class >> 8;
int ret, gen;
disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev);
- if (nv_device(drm->device)->card_type < NV_50)
- ret = nv04_display_create(dev);
- else
- if (nv_device(drm->device)->card_type < NV_D0)
- ret = nv50_display_create(dev);
- else
- ret = nvd0_display_create(dev);
- if (ret)
- goto disp_create_err;
-
- if (dev->mode_config.num_crtc) {
- ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (nouveau_modeset == 1 ||
+ (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
+ if (nv_device(drm->device)->card_type < NV_50)
+ ret = nv04_display_create(dev);
+ else
+ if (nv_device(drm->device)->card_type < NV_D0)
+ ret = nv50_display_create(dev);
+ else
+ ret = nvd0_display_create(dev);
if (ret)
- goto vblank_err;
+ goto disp_create_err;
+
+ if (dev->mode_config.num_crtc) {
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret)
+ goto vblank_err;
+ }
+
+ nouveau_backlight_init(dev);
}
- nouveau_backlight_init(dev);
return 0;
vblank_err:
@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
nouveau_backlight_exit(dev);
drm_vblank_cleanup(dev);
- disp->dtor(dev);
+ if (disp->dtor)
+ disp->dtor(dev);
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index ccae8c26ae2..0910125cbbc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
static int nouveau_noaccel = 0;
module_param_named(noaccel, nouveau_noaccel, int, 0400);
-MODULE_PARM_DESC(modeset, "enable driver");
-static int nouveau_modeset = -1;
+MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
+ "0 = disabled, 1 = enabled, 2 = headless)");
+int nouveau_modeset = -1;
module_param_named(modeset, nouveau_modeset, int, 0400);
static struct drm_driver driver;
@@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)
nouveau_pm_fini(dev);
- nouveau_display_fini(dev);
+ if (dev->mode_config.num_crtc)
+ nouveau_display_fini(dev);
nouveau_display_destroy(dev);
nouveau_irq_fini(dev);
@@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
pm_state.event == PM_EVENT_PRETHAW)
return 0;
- NV_INFO(drm, "suspending fbcon...\n");
- nouveau_fbcon_set_suspend(dev, 1);
+ if (dev->mode_config.num_crtc) {
+ NV_INFO(drm, "suspending fbcon...\n");
+ nouveau_fbcon_set_suspend(dev, 1);
- NV_INFO(drm, "suspending display...\n");
- ret = nouveau_display_suspend(dev);
- if (ret)
- return ret;
+ NV_INFO(drm, "suspending display...\n");
+ ret = nouveau_display_suspend(dev);
+ if (ret)
+ return ret;
+ }
NV_INFO(drm, "evicting buffers...\n");
ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
@@ -445,8 +449,10 @@ fail_client:
nouveau_client_init(&cli->base);
}
- NV_INFO(drm, "resuming display...\n");
- nouveau_display_resume(dev);
+ if (dev->mode_config.num_crtc) {
+ NV_INFO(drm, "resuming display...\n");
+ nouveau_display_resume(dev);
+ }
return ret;
}
@@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
nouveau_irq_postinstall(dev);
nouveau_pm_resume(dev);
- NV_INFO(drm, "resuming display...\n");
- nouveau_display_resume(dev);
+ if (dev->mode_config.num_crtc) {
+ NV_INFO(drm, "resuming display...\n");
+ nouveau_display_resume(dev);
+ }
return 0;
}
@@ -662,9 +670,7 @@ nouveau_drm_init(void)
#ifdef CONFIG_VGA_CONSOLE
if (vgacon_text_force())
nouveau_modeset = 0;
- else
#endif
- nouveau_modeset = 1;
}
if (!nouveau_modeset)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 81947121754..a1016992708 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
nv_info((cli), fmt, ##args); \
} while (0)
+extern int nouveau_modeset;
+
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 9ca8afdb554..1d8cb506a28 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
nv_subdev(pmc)->intr(nv_subdev(pmc));
- if (device->card_type >= NV_D0) {
- if (nv_rd32(device, 0x000100) & 0x04000000)
- nvd0_display_intr(dev);
- } else
- if (device->card_type >= NV_50) {
- if (nv_rd32(device, 0x000100) & 0x04000000)
- nv50_display_intr(dev);
+ if (dev->mode_config.num_crtc) {
+ if (device->card_type >= NV_D0) {
+ if (nv_rd32(device, 0x000100) & 0x04000000)
+ nvd0_display_intr(dev);
+ } else
+ if (device->card_type >= NV_50) {
+ if (nv_rd32(device, 0x000100) & 0x04000000)
+ nv50_display_intr(dev);
+ }
}
return IRQ_HANDLED;
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c
index 347a3bd78d0..64f7020fb60 100644
--- a/drivers/gpu/drm/nouveau/nv04_dac.c
+++ b/drivers/gpu/drm/nouveau/nv04_dac.c
@@ -220,7 +220,7 @@ out:
NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
if (blue == 0x18) {
- NV_INFO(drm, "Load detected on head A\n");
+ NV_DEBUG(drm, "Load detected on head A\n");
return connector_status_connected;
}
@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
if (nv17_dac_sample_load(encoder) &
NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
- NV_INFO(drm, "Load detected on output %c\n",
- '@' + ffs(dcb->or));
+ NV_DEBUG(drm, "Load detected on output %c\n",
+ '@' + ffs(dcb->or));
return connector_status_connected;
} else {
return connector_status_disconnected;
@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON);
- NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
- drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
- nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+ NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+ drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+ nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
}
void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
return;
nv_encoder->last_dpms = mode;
- NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
- mode, nv_encoder->dcb->index);
+ NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
+ mode, nv_encoder->dcb->index);
nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
}
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
index da55d7642c8..184cdf80676 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON);
- NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
- drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
- nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+ NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+ drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+ nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
}
static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
return;
nv_encoder->last_dpms = mode;
- NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
- mode, nv_encoder->dcb->index);
+ NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
+ mode, nv_encoder->dcb->index);
if (was_powersaving && is_powersaving_dpms(mode))
return;
@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
return;
nv_encoder->last_dpms = mode;
- NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
- mode, nv_encoder->dcb->index);
+ NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
+ mode, nv_encoder->dcb->index);
nv04_dfp_update_backlight(encoder, mode);
nv04_dfp_update_fp_control(encoder, mode);
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
index 099fbeda6e2..62e826a139b 100644
--- a/drivers/gpu/drm/nouveau/nv04_tv.c
+++ b/drivers/gpu/drm/nouveau/nv04_tv.c
@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
uint8_t crtc1A;
- NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
- mode, nv_encoder->dcb->index);
+ NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
+ mode, nv_encoder->dcb->index);
state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON);
- NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
- drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
- '@' + ffs(nv_encoder->dcb->or));
+ NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+ drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
}
static void nv04_tv_destroy(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 2e566e123e9..3bce0299f64 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1696,35 +1696,43 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
return ATOM_PPLL2;
DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID;
- } else {
- if (ASIC_IS_AVIVO(rdev)) {
- /* in DP mode, the DP ref clock can come from either PPLL
- * depending on the asic:
- * DCE3: PPLL1 or PPLL2
- */
- if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
- /* use the same PPLL for all DP monitors */
- pll = radeon_get_shared_dp_ppll(crtc);
- if (pll != ATOM_PPLL_INVALID)
- return pll;
- } else {
- /* use the same PPLL for all monitors with the same clock */
- pll = radeon_get_shared_nondp_ppll(crtc);
- if (pll != ATOM_PPLL_INVALID)
- return pll;
- }
- /* all other cases */
- pll_in_use = radeon_get_pll_use_mask(crtc);
+ } else if (ASIC_IS_AVIVO(rdev)) {
+ /* in DP mode, the DP ref clock can come from either PPLL
+ * depending on the asic:
+ * DCE3: PPLL1 or PPLL2
+ */
+ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+ /* use the same PPLL for all DP monitors */
+ pll = radeon_get_shared_dp_ppll(crtc);
+ if (pll != ATOM_PPLL_INVALID)
+ return pll;
+ } else {
+ /* use the same PPLL for all monitors with the same clock */
+ pll = radeon_get_shared_nondp_ppll(crtc);
+ if (pll != ATOM_PPLL_INVALID)
+ return pll;
+ }
+ /* all other cases */
+ pll_in_use = radeon_get_pll_use_mask(crtc);
+ /* the order shouldn't matter here, but we probably
+ * need this until we have atomic modeset
+ */
+ if (rdev->flags & RADEON_IS_IGP) {
if (!(pll_in_use & (1 << ATOM_PPLL1)))
return ATOM_PPLL1;
if (!(pll_in_use & (1 << ATOM_PPLL2)))
return ATOM_PPLL2;
- DRM_ERROR("unable to allocate a PPLL\n");
- return ATOM_PPLL_INVALID;
} else {
- /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
- return radeon_crtc->crtc_id;
+ if (!(pll_in_use & (1 << ATOM_PPLL2)))
+ return ATOM_PPLL2;
+ if (!(pll_in_use & (1 << ATOM_PPLL1)))
+ return ATOM_PPLL1;
}
+ DRM_ERROR("unable to allocate a PPLL\n");
+ return ATOM_PPLL_INVALID;
+ } else {
+ /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
+ return radeon_crtc->crtc_id;
}
}
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index ba498f8e47a..010bae19554 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -1625,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
/* some early dce3.2 boards have a bug in their transmitter control table */
- if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+ if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
}
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 14313ad43b7..af31f829f4a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1372,7 +1372,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
for (i = 0; i < rdev->num_crtc; i++) {
- if (save->crtc_enabled) {
+ if (save->crtc_enabled[i]) {
if (ASIC_IS_DCE6(rdev)) {
tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 30271b64191..c042e497e45 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
/* macro tile width & height */
palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
- mtileb = (palign / 8) * (halign / 8) * tileb;;
+ mtileb = (palign / 8) * (halign / 8) * tileb;
mtile_pr = surf->nbx / palign;
mtile_ps = (mtile_pr * surf->nby) / halign;
surf->layer_size = mtile_ps * mtileb * slice_pt;
@@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg)
/* check config regs */
switch (reg) {
case GRBM_GFX_INDEX:
+ case CP_STRMOUT_CNTL:
+ case CP_COHER_CNTL:
+ case CP_COHER_SIZE:
case VGT_VTX_VECT_EJECT_REG:
case VGT_CACHE_INVALIDATION:
case VGT_GS_VERTEX_REUSE:
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index df542f1a5df..2bc0f6a1b42 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -91,6 +91,10 @@
#define FB_READ_EN (1 << 0)
#define FB_WRITE_EN (1 << 1)
+#define CP_STRMOUT_CNTL 0x84FC
+
+#define CP_COHER_CNTL 0x85F0
+#define CP_COHER_SIZE 0x85F4
#define CP_COHER_BASE 0x85F8
#define CP_STALLED_STAT1 0x8674
#define CP_STALLED_STAT2 0x8678
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 37f6a907aea..15f5ded65e0 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
}
/**
- * radeon_atpx_switchto - switch to the requested GPU
+ * radeon_atpx_power_state - power down/up the requested GPU
*
- * @id: GPU to switch to
+ * @id: GPU to power down/up
* @state: requested power state (0 = off, 1 = on)
*
* Execute the necessary ATPX function to power down/up the discrete GPU
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 67cfc1795ec..b884c362a8c 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
struct drm_mode_object *obj;
int i;
enum drm_connector_status ret = connector_status_disconnected;
- bool dret = false;
+ bool dret = false, broken_edid = false;
if (!force && radeon_check_hpd_status_unchanged(connector))
return connector->status;
@@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
ret = connector_status_disconnected;
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
radeon_connector->ddc_bus = NULL;
+ } else {
+ ret = connector_status_connected;
+ broken_edid = true; /* defer use_digital to later */
}
} else {
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
@@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
encoder_funcs = encoder->helper_private;
if (encoder_funcs->detect) {
- if (ret != connector_status_connected) {
- ret = encoder_funcs->detect(encoder, connector);
- if (ret == connector_status_connected) {
- radeon_connector->use_digital = false;
+ if (!broken_edid) {
+ if (ret != connector_status_connected) {
+ /* deal with analog monitors without DDC */
+ ret = encoder_funcs->detect(encoder, connector);
+ if (ret == connector_status_connected) {
+ radeon_connector->use_digital = false;
+ }
+ if (ret != connector_status_disconnected)
+ radeon_connector->detected_by_load = true;
}
- if (ret != connector_status_disconnected)
- radeon_connector->detected_by_load = true;
+ } else {
+ enum drm_connector_status lret;
+ /* assume digital unless load detected otherwise */
+ radeon_connector->use_digital = true;
+ lret = encoder_funcs->detect(encoder, connector);
+ DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
+ if (lret == connector_status_connected)
+ radeon_connector->use_digital = false;
}
break;
}
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 5677a424b58..6857cb4efb7 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
+ uint32_t crtc_ext_cntl = 0;
uint32_t mask;
if (radeon_crtc->crtc_id)
@@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
RADEON_CRTC_VSYNC_DIS |
RADEON_CRTC_HSYNC_DIS);
+ /*
+ * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
+ * Therefore it is set in the DAC DMPS function.
+ * This is different for GPU's with a single CRTC but a primary and a
+ * TV DAC: here it controls the single CRTC no matter where it is
+ * routed. Therefore we set it here.
+ */
+ if (rdev->flags & RADEON_SINGLE_CRTC)
+ crtc_ext_cntl = RADEON_CRTC_CRT_ON;
+
switch (mode) {
case DRM_MODE_DPMS_ON:
radeon_crtc->enabled = true;
@@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B));
- WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
+ WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
}
drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
radeon_crtc_load_lut(crtc);
@@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B));
- WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
+ WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
}
radeon_crtc->enabled = false;
/* adjust pm to dpms changes AFTER disabling crtcs */
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 0063df9d166..f5ba2241dac 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
break;
}
- WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+ /* handled in radeon_crtc_dpms() */
+ if (!(rdev->flags & RADEON_SINGLE_CRTC))
+ WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
WREG32(RADEON_DAC_CNTL, dac_cntl);
WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
@@ -662,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
if (ASIC_IS_R300(rdev))
tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+ else if (ASIC_IS_RV100(rdev))
+ tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
else
tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
@@ -671,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
WREG32(RADEON_DAC_CNTL, tmp);
+ tmp = dac_macro_cntl;
tmp &= ~(RADEON_DAC_PDWN_R |
RADEON_DAC_PDWN_G |
RADEON_DAC_PDWN_B);
@@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
} else {
if (is_tv)
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
- else
+ /* handled in radeon_crtc_dpms() */
+ else if (!(rdev->flags & RADEON_SINGLE_CRTC))
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
}
@@ -1416,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
return found;
}
+static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
+ struct drm_connector *connector)
+{
+ struct drm_device *dev = encoder->dev;
+ struct radeon_device *rdev = dev->dev_private;
+ uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
+ uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
+ uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
+ uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
+ uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
+ bool found = false;
+ int i;
+
+ /* save the regs we need */
+ gpio_monid = RREG32(RADEON_GPIO_MONID);
+ fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+ disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+ crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+ disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
+ disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
+ disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
+ disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
+ disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
+ disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
+ crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
+ crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
+ crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
+ crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+ tmp = RREG32(RADEON_GPIO_MONID);
+ tmp &= ~RADEON_GPIO_A_0;
+ WREG32(RADEON_GPIO_MONID, tmp);
+
+ WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
+ RADEON_FP2_PANEL_FORMAT |
+ R200_FP2_SOURCE_SEL_TRANS_UNIT |
+ RADEON_FP2_DVO_EN |
+ R200_FP2_DVO_RATE_SEL_SDR));
+
+ WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
+ RADEON_DISP_TRANS_MATRIX_GRAPHICS));
+
+ WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
+ RADEON_CRTC2_DISP_REQ_EN_B));
+
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+
+ WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+ WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+ WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+ WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+ for (i = 0; i < 200; i++) {
+ tmp = RREG32(RADEON_GPIO_MONID);
+ if (tmp & RADEON_GPIO_Y_0)
+ found = true;
+
+ if (found)
+ break;
+
+ if (!drm_can_sleep())
+ mdelay(1);
+ else
+ msleep(1);
+ }
+
+ /* restore the regs we used */
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
+ WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
+ WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
+ WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
+ WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
+ WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
+ WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+ WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+ WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+ WREG32(RADEON_GPIO_MONID, gpio_monid);
+
+ return found;
+}
+
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
- uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
- uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+ uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+ uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
+ uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
enum drm_connector_status found = connector_status_disconnected;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
@@ -1459,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
return connector_status_disconnected;
}
+ /* R200 uses an external DAC for secondary DAC */
+ if (rdev->family == CHIP_R200) {
+ if (radeon_legacy_ext_dac_detect(encoder, connector))
+ found = connector_status_connected;
+ return found;
+ }
+
/* save the regs we need */
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
- gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
- disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
- disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
- crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+
+ if (rdev->flags & RADEON_SINGLE_CRTC) {
+ crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+ } else {
+ if (ASIC_IS_R300(rdev)) {
+ gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+ disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+ } else {
+ disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+ }
+ crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+ }
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
@@ -1473,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
| RADEON_PIX2CLK_DAC_ALWAYS_ONb);
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
- if (ASIC_IS_R300(rdev))
- WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
-
- tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
- tmp |= RADEON_CRTC2_CRT2_ON |
- (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
-
- WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
-
- if (ASIC_IS_R300(rdev)) {
- tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
- tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
- WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+ if (rdev->flags & RADEON_SINGLE_CRTC) {
+ tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+ WREG32(RADEON_CRTC_EXT_CNTL, tmp);
} else {
- tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
- WREG32(RADEON_DISP_HW_DEBUG, tmp);
+ tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+ tmp |= RADEON_CRTC2_CRT2_ON |
+ (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+ WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
+
+ if (ASIC_IS_R300(rdev)) {
+ WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
+ tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+ tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+ WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+ } else {
+ tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+ WREG32(RADEON_DISP_HW_DEBUG, tmp);
+ }
}
tmp = RADEON_TV_DAC_NBLANK |
@@ -1530,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
- WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
- if (ASIC_IS_R300(rdev)) {
- WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
- WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+ if (rdev->flags & RADEON_SINGLE_CRTC) {
+ WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
} else {
- WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+ WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+ if (ASIC_IS_R300(rdev)) {
+ WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+ WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+ } else {
+ WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+ }
}
+
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
return found;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index b0db712060f..4422d630b33 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -2474,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg)
/* check config regs */
switch (reg) {
case GRBM_GFX_INDEX:
+ case CP_STRMOUT_CNTL:
case VGT_VTX_VECT_EJECT_REG:
case VGT_CACHE_INVALIDATION:
case VGT_ESGS_RING_SIZE:
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 7d2a20e5657..a8871afc5b4 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -424,6 +424,7 @@
# define RDERR_INT_ENABLE (1 << 0)
# define GUI_IDLE_INT_ENABLE (1 << 19)
+#define CP_STRMOUT_CNTL 0x84FC
#define SCRATCH_REG0 0x8500
#define SCRATCH_REG1 0x8504
#define SCRATCH_REG2 0x8508
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 860dc4813e9..bd2a3b40cd1 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
/* clear the pages coming from the pool if requested */
if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) {
list_for_each_entry(p, &plist, lru) {
- clear_page(page_address(p));
+ if (PageHighMem(p))
+ clear_highpage(p);
+ else
+ clear_page(page_address(p));
}
}
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index bf8260133ea..7d759a43029 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
if (unlikely(to_page == NULL))
goto out_err;
- preempt_disable();
copy_highpage(to_page, from_page);
- preempt_enable();
page_cache_release(from_page);
}
@@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
ret = PTR_ERR(to_page);
goto out_err;
}
- preempt_disable();
copy_highpage(to_page, from_page);
- preempt_enable();
set_page_dirty(to_page);
mark_page_accessed(to_page);
page_cache_release(to_page);
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index fccd361f7b5..87aa5f5d3c8 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
const char *front, char **urb_buf_ptr,
- u32 byte_offset, u32 byte_width,
+ u32 byte_offset, u32 device_byte_offset, u32 byte_width,
int *ident_ptr, int *sent_ptr);
int udl_dumb_create(struct drm_file *file_priv,
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index 69a2b16f42a..d4ab3beaada 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
- &urb, (char *) info->fix.smem_start,
- &cmd, cur->index << PAGE_SHIFT,
- PAGE_SIZE, &bytes_identical, &bytes_sent))
+ &urb, (char *) info->fix.smem_start,
+ &cmd, cur->index << PAGE_SHIFT,
+ cur->index << PAGE_SHIFT,
+ PAGE_SIZE, &bytes_identical, &bytes_sent))
goto error;
bytes_rendered += PAGE_SIZE;
}
@@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
for (i = y; i < y + height ; i++) {
const int line_offset = fb->base.pitches[0] * i;
const int byte_offset = line_offset + (x * bpp);
-
+ const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
if (udl_render_hline(dev, bpp, &urb,
(char *) fb->obj->vmapping,
- &cmd, byte_offset, width * bpp,
+ &cmd, byte_offset, dev_byte_offset,
+ width * bpp,
&bytes_identical, &bytes_sent))
goto error;
}
diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c
index dc095526ffb..142fee5f983 100644
--- a/drivers/gpu/drm/udl/udl_transfer.c
+++ b/drivers/gpu/drm/udl/udl_transfer.c
@@ -213,11 +213,12 @@ static void udl_compress_hline16(
*/
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
const char *front, char **urb_buf_ptr,
- u32 byte_offset, u32 byte_width,
+ u32 byte_offset, u32 device_byte_offset,
+ u32 byte_width,
int *ident_ptr, int *sent_ptr)
{
const u8 *line_start, *line_end, *next_pixel;
- u32 base16 = 0 + (byte_offset / bpp) * 2;
+ u32 base16 = 0 + (device_byte_offset / bpp) * 2;
struct urb *urb = *urb_ptr;
u8 *cmd = *urb_buf_ptr;
u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
index 3ce68a2e312..d1498bfd787 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
BUG_ON(!atomic_read(&bo->reserved));
BUG_ON(old_mem_type != TTM_PL_VRAM &&
- old_mem_type != VMW_PL_FLAG_GMR);
+ old_mem_type != VMW_PL_GMR);
pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
if (pin)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index ed3c1e7ddde..2dd185e42f2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev)
struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev);
+ mutex_lock(&dev_priv->hw_mutex);
+ vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
+ (void) vmw_read(dev_priv, SVGA_REG_ID);
+ mutex_unlock(&dev_priv->hw_mutex);
+
/**
* Reclaim 3d reference held by fbdev and potentially
* start fifo.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index b07ca2e4d04..7290811f89b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
ret = copy_to_user(buffer, bounce, size);
+ if (ret)
+ ret = -EFAULT;
vfree(bounce);
if (unlikely(ret != 0))
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 06ebdbb6ea0..fd7722aecf7 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bd3971bf31b..f4109fd657f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ }
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 269b50912a4..9d7a42857ea 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -118,6 +118,9 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 3acdcfcc17d..6fcd466d082 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -28,22 +28,30 @@
#define MS_RDESC 0x08
#define MS_NOGET 0x10
#define MS_DUPLICATE_USAGES 0x20
+#define MS_RDESC_3K 0x40
-/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has
- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
- */
static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+ /*
+ * Microsoft Wireless Desktop Receiver (Model 1028) has
+ * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+ */
if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
rdesc[559] == 0x29) {
hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
rdesc[557] = 0x35;
rdesc[559] = 0x45;
}
+ /* the same as above (s/usage/physical/) */
+ if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 &&
+ rdesc[95] == 0x00 && rdesc[96] == 0x29 &&
+ rdesc[97] == 0xff) {
+ rdesc[94] = 0x35;
+ rdesc[96] = 0x45;
+ }
return rdesc;
}
@@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
.driver_data = MS_PRESENTER },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
- .driver_data = MS_ERGONOMY },
+ .driver_data = MS_ERGONOMY | MS_RDESC_3K },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
.driver_data = MS_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 3eb02b94fc8..7867d69f0ef 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
},
{ .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
- MT_QUIRK_SLOT_IS_CONTACTNUMBER,
- .maxcontacts = 10
+ MT_QUIRK_SLOT_IS_CONTACTNUMBER
},
{ .name = MT_CLS_FLATFROG,
@@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
* contact max are global to the report */
td->last_field_index = field->index;
return -1;
- }
case HID_DG_TOUCH:
/* Legacy devices use TIPSWITCH and not TOUCH.
* Let's just ignore this field. */
return -1;
+ }
/* let hid-input decide for the others */
return 0;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 17d15bb610d..7c47fc3f7b2 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -42,7 +42,6 @@ static struct cdev hidraw_cdev;
static struct class *hidraw_class;
static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
static DEFINE_MUTEX(minors_lock);
-static void drop_ref(struct hidraw *hid, int exists_bit);
static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
@@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
__u8 *buf;
int ret = 0;
- if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+ if (!hidraw_table[minor]) {
ret = -ENODEV;
goto out;
}
@@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
}
mutex_lock(&minors_lock);
- if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+ if (!hidraw_table[minor]) {
err = -ENODEV;
goto out_unlock;
}
@@ -299,12 +298,36 @@ out:
static int hidraw_release(struct inode * inode, struct file * file)
{
unsigned int minor = iminor(inode);
+ struct hidraw *dev;
struct hidraw_list *list = file->private_data;
+ int ret;
+ int i;
+
+ mutex_lock(&minors_lock);
+ if (!hidraw_table[minor]) {
+ ret = -ENODEV;
+ goto unlock;
+ }
- drop_ref(hidraw_table[minor], 0);
list_del(&list->node);
+ dev = hidraw_table[minor];
+ if (!--dev->open) {
+ if (list->hidraw->exist) {
+ hid_hw_power(dev->hid, PM_HINT_NORMAL);
+ hid_hw_close(dev->hid);
+ } else {
+ kfree(list->hidraw);
+ }
+ }
+
+ for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
+ kfree(list->buffer[i].value);
kfree(list);
- return 0;
+ ret = 0;
+unlock:
+ mutex_unlock(&minors_lock);
+
+ return ret;
}
static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect);
void hidraw_disconnect(struct hid_device *hid)
{
struct hidraw *hidraw = hid->hidraw;
- drop_ref(hidraw, 1);
+
+ mutex_lock(&minors_lock);
+ hidraw->exist = 0;
+
+ device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+
+ hidraw_table[hidraw->minor] = NULL;
+
+ if (hidraw->open) {
+ hid_hw_close(hid);
+ wake_up_interruptible(&hidraw->wait);
+ } else {
+ kfree(hidraw);
+ }
+ mutex_unlock(&minors_lock);
}
EXPORT_SYMBOL_GPL(hidraw_disconnect);
@@ -555,23 +592,3 @@ void hidraw_exit(void)
unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
}
-
-static void drop_ref(struct hidraw *hidraw, int exists_bit)
-{
- mutex_lock(&minors_lock);
- if (exists_bit) {
- hid_hw_close(hidraw->hid);
- hidraw->exist = 0;
- if (hidraw->open)
- wake_up_interruptible(&hidraw->wait);
- } else {
- --hidraw->open;
- }
-
- if (!hidraw->open && !hidraw->exist) {
- device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
- hidraw_table[hidraw->minor] = NULL;
- kfree(hidraw);
- }
- mutex_unlock(&minors_lock);
-}
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index a227be47149..520e5bf4f76 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -32,7 +32,7 @@
* ASB100-A supports pwm1, while plain ASB100 does not. There is no known
* way for the driver to tell which one is there.
*
- * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* asb100 7 3 1 4 0x31 0x0694 yes no
*/
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 68ad7d25551..4f411040738 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -2,7 +2,7 @@
* fam15h_power.c - AMD Family 15h processor power monitoring
*
* Copyright (c) 2011 Advanced Micro Devices, Inc.
- * Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+ * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
*
*
* This driver is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
#include <asm/processor.h>
MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
-MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
+MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
MODULE_LICENSE("GPL");
/* D18F3 */
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 36509ae3208..1381a2e3bbd 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
.driver = {
.name = "gpio-fan",
.pm = GPIO_FAN_PM,
+#ifdef CONFIG_OF_GPIO
.of_match_table = of_match_ptr(of_gpio_fan_match),
+#endif
},
};
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 1821b7423d5..de3c7e04c3b 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
mutex_init(&data->lock);
mutex_init(&data->update_lock);
data->name = w83627ehf_device_names[sio_data->kind];
+ data->bank = 0xff; /* Force initial bank selection */
platform_set_drvdata(pdev, data);
/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 5b1a6a66644..af158990870 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -25,7 +25,7 @@
/*
* Supports following chips:
*
- * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC)
* w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC)
* w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC)
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 5a5046d94c3..20f11d31da4 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -24,7 +24,7 @@
/*
* Supports following chips:
*
- * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* as99127f 7 3 0 3 0x31 0x12c3 yes no
* as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
* w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 39ab7bcc616..ed397c64519 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -22,7 +22,7 @@
/*
* Supports following chips:
*
- * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83791d 10 5 5 3 0x71 0x5ca3 yes no
*
* The w83791d chip appears to be part way between the 83781d and the
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 053645279f3..301942d0845 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -31,7 +31,7 @@
/*
* Supports following chips:
*
- * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83792d 9 7 7 3 0x7a 0x5ca3 yes no
*/
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index f0e8286c3c7..79710bcac2f 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -20,7 +20,7 @@
/*
* Supports following chips:
*
- * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+ * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
* w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no
*/
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index beee6b2d361..1722f50f247 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
obj-y += algos/ busses/ muxes/
+obj-$(CONFIG_I2C_STUB) += i2c-stub.o
ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
CFLAGS_i2c-core.o := -Wno-deprecated-declarations
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 65dd599a026..e9df4612b7e 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -81,7 +81,6 @@ config I2C_I801
tristate "Intel 82801 (ICH/PCH)"
depends on PCI
select CHECK_SIGNATURE if X86 && DMI
- select GPIOLIB if I2C_MUX
help
If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 2d33d62952c..395b516ffa0 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
-obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 37793156bd9..6abc00d5988 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -82,7 +82,8 @@
#include <linux/wait.h>
#include <linux/err.h>
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+ defined CONFIG_DMI
#include <linux/gpio.h>
#include <linux/i2c-mux-gpio.h>
#include <linux/platform_device.h>
@@ -192,7 +193,8 @@ struct i801_priv {
int len;
u8 *data;
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+ defined CONFIG_DMI
const struct i801_mux_config *mux_drvdata;
struct platform_device *mux_pdev;
#endif
@@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}
static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
#endif /* CONFIG_X86 && CONFIG_DMI */
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+ defined CONFIG_DMI
static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
.gpio_chip = "gpio_ich",
.values = { 0x02, 0x03 },
@@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
id = dmi_first_match(mux_dmi_table);
if (id) {
- /* Remove from branch classes from trunk */
+ /* Remove branch classes from trunk */
mux_config = id->driver_data;
for (i = 0; i < mux_config->n_values; i++)
class &= ~mux_config->classes[i];
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 2ef162d148c..b9734747d61 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -52,8 +52,6 @@
#include <linux/of_device.h>
#include <linux/of_i2c.h>
#include <linux/pinctrl/consumer.h>
-
-#include <mach/hardware.h>
#include <linux/platform_data/i2c-imx.h>
/** Defines ********************************************************************
@@ -115,6 +113,11 @@ static u16 __initdata i2c_clk_div[50][2] = {
{ 3072, 0x1E }, { 3840, 0x1F }
};
+enum imx_i2c_type {
+ IMX1_I2C,
+ IMX21_I2C,
+};
+
struct imx_i2c_struct {
struct i2c_adapter adapter;
struct clk *clk;
@@ -124,13 +127,33 @@ struct imx_i2c_struct {
unsigned int disable_delay;
int stopped;
unsigned int ifdr; /* IMX_I2C_IFDR */
+ enum imx_i2c_type devtype;
+};
+
+static struct platform_device_id imx_i2c_devtype[] = {
+ {
+ .name = "imx1-i2c",
+ .driver_data = IMX1_I2C,
+ }, {
+ .name = "imx21-i2c",
+ .driver_data = IMX21_I2C,
+ }, {
+ /* sentinel */
+ }
};
+MODULE_DEVICE_TABLE(platform, imx_i2c_devtype);
static const struct of_device_id i2c_imx_dt_ids[] = {
- { .compatible = "fsl,imx1-i2c", },
+ { .compatible = "fsl,imx1-i2c", .data = &imx_i2c_devtype[IMX1_I2C], },
+ { .compatible = "fsl,imx21-i2c", .data = &imx_i2c_devtype[IMX21_I2C], },
{ /* sentinel */ }
};
+static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)
+{
+ return i2c_imx->devtype == IMX1_I2C;
+}
+
/** Functions for IMX I2C adapter driver ***************************************
*******************************************************************************/
@@ -223,7 +246,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
temp &= ~(I2CR_MSTA | I2CR_MTX);
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
}
- if (cpu_is_mx1()) {
+ if (is_imx1_i2c(i2c_imx)) {
/*
* This delay caused by an i.MXL hardware bug.
* If no (or too short) delay, no "STOP" bit will be generated.
@@ -465,6 +488,8 @@ static struct i2c_algorithm i2c_imx_algo = {
static int __init i2c_imx_probe(struct platform_device *pdev)
{
+ const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids,
+ &pdev->dev);
struct imx_i2c_struct *i2c_imx;
struct resource *res;
struct imxi2c_platform_data *pdata = pdev->dev.platform_data;
@@ -497,6 +522,10 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ i2c_imx->devtype = pdev->id_entry->driver_data;
+
/* Setup i2c_imx driver structure */
strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
i2c_imx->adapter.owner = THIS_MODULE;
@@ -593,7 +622,8 @@ static struct platform_driver i2c_imx_driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = i2c_imx_dt_ids,
- }
+ },
+ .id_table = imx_i2c_devtype,
};
static int __init i2c_adap_imx_init(void)
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 1f58197062c..286ca191782 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -1,7 +1,7 @@
/*
* Freescale MXS I2C bus driver
*
- * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
*
* based on a (non-working) driver which was:
*
@@ -35,10 +35,6 @@
#define DRIVER_NAME "mxs-i2c"
-static bool use_pioqueue;
-module_param(use_pioqueue, bool, 0);
-MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
-
#define MXS_I2C_CTRL0 (0x00)
#define MXS_I2C_CTRL0_SET (0x04)
@@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
MXS_I2C_CTRL1_SLAVE_IRQ)
-#define MXS_I2C_QUEUECTRL (0x60)
-#define MXS_I2C_QUEUECTRL_SET (0x64)
-#define MXS_I2C_QUEUECTRL_CLR (0x68)
-
-#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20
-#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04
-
-#define MXS_I2C_QUEUESTAT (0x70)
-#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000
-#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
-
-#define MXS_I2C_QUEUECMD (0x80)
-
-#define MXS_I2C_QUEUEDATA (0x90)
-
-#define MXS_I2C_DATA (0xa0)
-
#define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \
MXS_I2C_CTRL0_PRE_SEND_START | \
@@ -153,7 +132,6 @@ struct mxs_i2c_dev {
const struct mxs_i2c_speed_config *speed;
/* DMA support components */
- bool dma_mode;
int dma_channel;
struct dma_chan *dmach;
struct mxs_dma_data dma_data;
@@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
- if (i2c->dma_mode)
- writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
- i2c->regs + MXS_I2C_QUEUECTRL_CLR);
- else
- writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
- i2c->regs + MXS_I2C_QUEUECTRL_SET);
-}
-
-static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
- int flags)
-{
- u32 data;
-
- writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
-
- data = (addr << 1) | I2C_SMBUS_READ;
- writel(data, i2c->regs + MXS_I2C_DATA);
-
- data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
- writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-}
-
-static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
- u8 addr, u8 *buf, int len, int flags)
-{
- u32 data;
- int i, shifts_left;
-
- data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
- writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-
- /*
- * We have to copy the slave address (u8) and buffer (arbitrary number
- * of u8) into the data register (u32). To achieve that, the u8 are put
- * into the MSBs of 'data' which is then shifted for the next u8. When
- * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
- * looks like this:
- *
- * 3 2 1 0
- * 10987654|32109876|54321098|76543210
- * --------+--------+--------+--------
- * buffer+2|buffer+1|buffer+0|slave_addr
- */
-
- data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
-
- for (i = 0; i < len; i++) {
- data >>= 8;
- data |= buf[i] << 24;
- if ((i & 3) == 2)
- writel(data, i2c->regs + MXS_I2C_DATA);
- }
-
- /* Write out the remaining bytes if any */
- shifts_left = 24 - (i & 3) * 8;
- if (shifts_left)
- writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
-}
-
-/*
- * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
- * rd_threshold to 1). Couldn't get this to work, though.
- */
-static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
- while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
- & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
- if (time_after(jiffies, timeout))
- return -ETIMEDOUT;
- cond_resched();
- }
-
- return 0;
-}
-
-static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
-{
- u32 uninitialized_var(data);
- int i;
-
- for (i = 0; i < len; i++) {
- if ((i & 3) == 0) {
- if (mxs_i2c_wait_for_data(i2c))
- return -ETIMEDOUT;
- data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
- }
- buf[i] = data & 0xff;
- data >>= 8;
- }
-
- return 0;
}
static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
@@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
init_completion(&i2c->cmd_complete);
i2c->cmd_err = 0;
- if (i2c->dma_mode) {
- ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
- if (ret)
- return ret;
- } else {
- if (msg->flags & I2C_M_RD) {
- mxs_i2c_pioq_setup_read(i2c, msg->addr,
- msg->len, flags);
- } else {
- mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
- msg->len, flags);
- }
-
- writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
- i2c->regs + MXS_I2C_QUEUECTRL_SET);
- }
+ ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+ if (ret)
+ return ret;
ret = wait_for_completion_timeout(&i2c->cmd_complete,
msecs_to_jiffies(1000));
if (ret == 0)
goto timeout;
- if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
- ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
- if (ret)
- goto timeout;
- }
-
if (i2c->cmd_err == -ENXIO)
mxs_i2c_reset(i2c);
- else
- writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
- i2c->regs + MXS_I2C_QUEUECTRL_CLR);
dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
@@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
timeout:
dev_dbg(i2c->dev, "Timeout!\n");
- if (i2c->dma_mode)
- mxs_i2c_dma_finish(i2c);
+ mxs_i2c_dma_finish(i2c);
mxs_i2c_reset(i2c);
return -ETIMEDOUT;
}
@@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
{
struct mxs_i2c_dev *i2c = dev_id;
u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
- bool is_last_cmd;
if (!stat)
return IRQ_NONE;
@@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
i2c->cmd_err = -EIO;
- if (!i2c->dma_mode) {
- is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
- MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
-
- if (is_last_cmd || i2c->cmd_err)
- complete(&i2c->cmd_complete);
- }
-
writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
return IRQ_HANDLED;
@@ -556,23 +409,14 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
int ret;
/*
- * The MXS I2C DMA mode is prefered and enabled by default.
- * The PIO mode is still supported, but should be used only
- * for debuging purposes etc.
- */
- i2c->dma_mode = !use_pioqueue;
- if (!i2c->dma_mode)
- dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
-
- /*
* TODO: This is a temporary solution and should be changed
* to use generic DMA binding later when the helpers get in.
*/
ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
&i2c->dma_channel);
if (ret) {
- dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
- i2c->dma_mode = 0;
+ dev_err(dev, "Failed to get DMA channel!\n");
+ return -ENODEV;
}
ret = of_property_read_u32(node, "clock-frequency", &speed);
@@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
}
/* Setup the DMA */
- if (i2c->dma_mode) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- i2c->dma_data.chan_irq = dmairq;
- i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
- if (!i2c->dmach) {
- dev_err(dev, "Failed to request dma\n");
- return -ENODEV;
- }
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ i2c->dma_data.chan_irq = dmairq;
+ i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+ if (!i2c->dmach) {
+ dev_err(dev, "Failed to request dma\n");
+ return -ENODEV;
}
platform_set_drvdata(pdev, i2c);
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 698d7acb0f0..02c3115a2df 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
pm_runtime_get_sync(&dev->adev->dev);
- clk_enable(dev->clk);
+ status = clk_prepare_enable(dev->clk);
+ if (status) {
+ dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
+ goto out_clk;
+ }
status = init_hw(dev);
if (status)
@@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
}
out:
- clk_disable(dev->clk);
+ clk_disable_unprepare(dev->clk);
+out_clk:
pm_runtime_put_sync(&dev->adev->dev);
dev->busy = false;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index f981ac4e678..dcea77bf6f5 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
}
ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
- tegra_i2c_isr, 0, pdev->name, i2c_dev);
+ tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
return ret;
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/i2c-stub.c
index b1b3447942c..d0a9c590c3c 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/i2c-stub.c
@@ -2,7 +2,7 @@
i2c-stub.c - I2C/SMBus chip emulator
Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
- Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
+ Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>
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
@@ -51,8 +51,8 @@ struct stub_chip {
static struct stub_chip *stub_chips;
/* Return negative errno on error. */
-static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
- char read_write, u8 command, int size, union i2c_smbus_data * data)
+static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+ char read_write, u8 command, int size, union i2c_smbus_data *data)
{
s32 ret;
int i, len;
@@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_WRITE) {
chip->pointer = command;
- dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
- "wrote 0x%02x.\n",
- addr, command);
+ dev_dbg(&adap->dev,
+ "smbus byte - addr 0x%02x, wrote 0x%02x.\n",
+ addr, command);
} else {
data->byte = chip->words[chip->pointer++] & 0xff;
- dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
- "read 0x%02x.\n",
- addr, data->byte);
+ dev_dbg(&adap->dev,
+ "smbus byte - addr 0x%02x, read 0x%02x.\n",
+ addr, data->byte);
}
ret = 0;
@@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
if (read_write == I2C_SMBUS_WRITE) {
chip->words[command] &= 0xff00;
chip->words[command] |= data->byte;
- dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
- "wrote 0x%02x at 0x%02x.\n",
- addr, data->byte, command);
+ dev_dbg(&adap->dev,
+ "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
+ addr, data->byte, command);
} else {
data->byte = chip->words[command] & 0xff;
- dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
- "read 0x%02x at 0x%02x.\n",
- addr, data->byte, command);
+ dev_dbg(&adap->dev,
+ "smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n",
+ addr, data->byte, command);
}
chip->pointer = command + 1;
@@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
case I2C_SMBUS_WORD_DATA:
if (read_write == I2C_SMBUS_WRITE) {
chip->words[command] = data->word;
- dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
- "wrote 0x%04x at 0x%02x.\n",
- addr, data->word, command);
+ dev_dbg(&adap->dev,
+ "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
+ addr, data->word, command);
} else {
data->word = chip->words[command];
- dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
- "read 0x%04x at 0x%02x.\n",
- addr, data->word, command);
+ dev_dbg(&adap->dev,
+ "smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n",
+ addr, data->word, command);
}
ret = 0;
@@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
chip->words[command + i] &= 0xff00;
chip->words[command + i] |= data->block[1 + i];
}
- dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
- "wrote %d bytes at 0x%02x.\n",
- addr, len, command);
+ dev_dbg(&adap->dev,
+ "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+ addr, len, command);
} else {
for (i = 0; i < len; i++) {
data->block[1 + i] =
chip->words[command + i] & 0xff;
}
- dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
- "read %d bytes at 0x%02x.\n",
- addr, len, command);
+ dev_dbg(&adap->dev,
+ "i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n",
+ addr, len, command);
}
ret = 0;
@@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)
int i, ret;
if (!chip_addr[0]) {
- printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
+ pr_err("i2c-stub: Please specify a chip address\n");
return -ENODEV;
}
for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
- printk(KERN_ERR "i2c-stub: Invalid chip address "
- "0x%02x\n", chip_addr[i]);
+ pr_err("i2c-stub: Invalid chip address 0x%02x\n",
+ chip_addr[i]);
return -EINVAL;
}
- printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n",
- chip_addr[i]);
+ pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
}
/* Allocate memory for all chips at once */
stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
if (!stub_chips) {
- printk(KERN_ERR "i2c-stub: Out of memory\n");
+ pr_err("i2c-stub: Out of memory\n");
return -ENOMEM;
}
@@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");
module_init(i2c_stub_init);
module_exit(i2c_stub_exit);
-
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 5f097f309b9..7fa5b24b16d 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
mux->busses = devm_kzalloc(&pdev->dev,
sizeof(mux->busses) * mux->pdata->bus_count,
GFP_KERNEL);
- if (!mux->states) {
+ if (!mux->busses) {
dev_err(&pdev->dev, "Cannot allocate busses\n");
ret = -ENOMEM;
goto err;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index b4b65af8612..de0874054e9 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
config KEYBOARD_LPC32XX
tristate "LPC32XX matrix key scanner support"
depends on ARCH_LPC32XX && OF
+ select INPUT_MATRIXKMAP
help
Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
connected to a key matrix.
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 803ff6fe021..cad9d5dd597 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
unsigned int mask = 0, direct_key_num = 0;
unsigned long kpc = 0;
+ /* clear pending interrupt bit */
+ keypad_readl(KPC);
+
/* enable matrix keys with automatic scan */
if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index 02ca8680ea5..6f7d9901303 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
case XenbusStateReconfiguring:
case XenbusStateReconfigured:
case XenbusStateUnknown:
- case XenbusStateClosed:
break;
case XenbusStateInitWait:
@@ -350,6 +349,10 @@ InitWait:
break;
+ case XenbusStateClosed:
+ if (dev->state == XenbusStateClosed)
+ break;
+ /* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing:
xenbus_frontend_closed(dev);
break;
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 3a78f235fa3..2baff1b79a5 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -84,6 +84,10 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263
#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264
+/* MacbookPro10,2 (unibody, October 2012) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b
#define BCM5974_DEVICE(prod) { \
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
@@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
+ /* MacbookPro10,2 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
/* Terminating entry */
{}
};
@@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
{ SN_COORD, -150, 6730 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0x84, sizeof(struct bt_data),
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ { SN_PRESSURE, 0, 300 },
+ { SN_WIDTH, 0, 2048 },
+ { SN_COORD, -4750, 5280 },
+ { SN_COORD, -150, 6730 },
+ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
+ },
{}
};
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2c1e12bf2ab..858ad446de9 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
features->pktlen = WACOM_PKGLEN_TPC2FG;
}
- if (features->type == MTSCREEN || WACOM_24HDT)
+ if (features->type == MTSCREEN || features->type == WACOM_24HDT)
features->pktlen = WACOM_PKGLEN_MTOUCH;
if (features->type == BAMBOO_PT) {
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index aa601013117..0a67031ffc1 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1518,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
wacom_setup_cintiq(wacom_wac);
break;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 1ba232cbc09..f7668b24c37 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
config TOUCHSCREEN_EGALAX
tristate "EETI eGalax multi-touch panel support"
- depends on I2C
+ depends on I2C && OF
help
Say Y here to enable support for I2C connected EETI
eGalax multi-touch panels.
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index c1e3460f119..13fa62fdfb0 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/input/mt.h>
+#include <linux/of_gpio.h>
/*
* Mouse Mode: some panel may configure the controller to mouse mode,
@@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
/* wake up controller by an falling edge of interrupt gpio. */
static int egalax_wake_up_device(struct i2c_client *client)
{
- int gpio = irq_to_gpio(client->irq);
+ struct device_node *np = client->dev.of_node;
+ int gpio;
int ret;
+ if (!np)
+ return -ENODEV;
+
+ gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
+ if (!gpio_is_valid(gpio))
+ return -ENODEV;
+
ret = gpio_request(gpio, "egalax_irq");
if (ret < 0) {
dev_err(&client->dev,
@@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
ts->input_dev = input_dev;
/* controller may be in sleep, wake it up. */
- egalax_wake_up_device(client);
+ error = egalax_wake_up_device(client);
+ if (error) {
+ dev_err(&client->dev, "Failed to wake up the controller\n");
+ goto err_free_dev;
+ }
ret = egalax_firmware_version(client);
if (ret < 0) {
@@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
+static struct of_device_id egalax_ts_dt_ids[] = {
+ { .compatible = "eeti,egalax_ts" },
+ { /* sentinel */ }
+};
+
static struct i2c_driver egalax_ts_driver = {
.driver = {
.name = "egalax_ts",
.owner = THIS_MODULE,
.pm = &egalax_ts_pm_ops,
+ .of_match_table = of_match_ptr(egalax_ts_dt_ids),
},
.id_table = egalax_ts_id,
.probe = egalax_ts_probe,
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c
index 63209aaa55f..eb96f168fb9 100644
--- a/drivers/input/touchscreen/tsc40.c
+++ b/drivers/input/touchscreen/tsc40.c
@@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
__set_bit(BTN_TOUCH, input_dev->keybit);
input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
- input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
serio_set_drvdata(serio, ptsc);
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index a649f146d17..41678639b7e 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -34,13 +34,11 @@
#include <linux/of_iommu.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/tegra-ahb.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
-#include <mach/iomap.h>
-#include <mach/tegra-ahb.h>
-
enum smmu_hwgrp {
HWGRP_AFI,
HWGRP_AVPC,
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
index dc670ccc697..16c78f1c5ef 100644
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -168,7 +168,8 @@ static int __init armctrl_of_init(struct device_node *node,
}
static struct of_device_id irq_of_match[] __initconst = {
- { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }
+ { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init },
+ { }
};
void __init bcm2835_init_irq(void)
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index a233ed53913..86cd75a0e84 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -4,7 +4,7 @@
menuconfig ISDN
bool "ISDN support"
- depends on NET
+ depends on NET && NETDEVICES
depends on !S390 && !UML
---help---
ISDN ("Integrated Services Digital Network", called RNIS in France)
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 2302fbe70ac..9c6650ea848 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -6,7 +6,7 @@ if ISDN_I4L
config ISDN_PPP
bool "Support synchronous PPP"
- depends on INET && NETDEVICES
+ depends on INET
select SLHC
help
Over digital connections such as ISDN, there is no need to
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 8c610fa6782..e2a945ee9f0 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
} else
return -EINVAL;
break;
-#ifdef CONFIG_NETDEVICES
case IIOCNETGPN:
/* Get peer phone number of a connected
* isdn network interface */
@@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
return isdn_net_getpeer(&phone, argp);
} else
return -EINVAL;
-#endif
default:
return -EINVAL;
}
@@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
case IIOCNETLCR:
printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
return -ENODEV;
-#ifdef CONFIG_NETDEVICES
case IIOCNETAIF:
/* Add a network-interface */
if (arg) {
@@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
return -EFAULT;
return isdn_net_force_hangup(name);
break;
-#endif /* CONFIG_NETDEVICES */
case IIOCSETVER:
dev->net_verbose = arg;
printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index f508defc0d9..b58bc8a14b9 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -379,7 +379,9 @@ config LEDS_NS2
tristate "LED support for Network Space v2 GPIO LEDs"
depends on LEDS_CLASS
depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || \
- MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2
+ MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2 || \
+ MACH_NETSPACE_V2_DT || MACH_INETSPACE_V2_DT || \
+ MACH_NETSPACE_MAX_V2_DT || MACH_NETSPACE_MINI_V2_DT
default y
help
This option enable support for the dual-GPIO LED found on the
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index d176ec83f5d..d64cc2227fd 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -30,6 +30,7 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/platform_data/leds-kirkwood-ns2.h>
+#include <linux/of_gpio.h>
/*
* The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in
@@ -263,6 +264,62 @@ static void delete_ns2_led(struct ns2_led_data *led_dat)
gpio_free(led_dat->slow);
}
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data.
+ */
+static int __devinit
+ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+ struct device_node *child;
+ struct ns2_led *leds;
+ int num_leds = 0;
+ int i = 0;
+
+ num_leds = of_get_child_count(np);
+ if (!num_leds)
+ return -ENODEV;
+
+ leds = devm_kzalloc(dev, num_leds * sizeof(struct ns2_led),
+ GFP_KERNEL);
+ if (!leds)
+ return -ENOMEM;
+
+ for_each_child_of_node(np, child) {
+ const char *string;
+ int ret;
+
+ ret = of_get_named_gpio(child, "cmd-gpio", 0);
+ if (ret < 0)
+ return ret;
+ leds[i].cmd = ret;
+ ret = of_get_named_gpio(child, "slow-gpio", 0);
+ if (ret < 0)
+ return ret;
+ leds[i].slow = ret;
+ ret = of_property_read_string(child, "label", &string);
+ leds[i].name = (ret == 0) ? string : child->name;
+ ret = of_property_read_string(child, "linux,default-trigger",
+ &string);
+ if (ret == 0)
+ leds[i].default_trigger = string;
+
+ i++;
+ }
+
+ pdata->leds = leds;
+ pdata->num_leds = num_leds;
+
+ return 0;
+}
+
+static const struct of_device_id of_ns2_leds_match[] = {
+ { .compatible = "lacie,ns2-leds", },
+ {},
+};
+#endif /* CONFIG_OF_GPIO */
+
static int __devinit ns2_led_probe(struct platform_device *pdev)
{
struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
@@ -270,11 +327,25 @@ static int __devinit ns2_led_probe(struct platform_device *pdev)
int i;
int ret;
+#ifdef CONFIG_OF_GPIO
+ if (!pdata) {
+ pdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct ns2_led_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ ret = ns2_leds_get_of_pdata(&pdev->dev, pdata);
+ if (ret)
+ return ret;
+ }
+#else
if (!pdata)
return -EINVAL;
+#endif /* CONFIG_OF_GPIO */
leds_data = devm_kzalloc(&pdev->dev, sizeof(struct ns2_led_data) *
- pdata->num_leds, GFP_KERNEL);
+ pdata->num_leds, GFP_KERNEL);
if (!leds_data)
return -ENOMEM;
@@ -312,8 +383,9 @@ static struct platform_driver ns2_led_driver = {
.probe = ns2_led_probe,
.remove = __devexit_p(ns2_led_remove),
.driver = {
- .name = "leds-ns2",
- .owner = THIS_MODULE,
+ .name = "leds-ns2",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(of_ns2_leds_match),
},
};
diff --git a/drivers/leds/ledtrig-cpu.c b/drivers/leds/ledtrig-cpu.c
index b312056da14..4239b3955ff 100644
--- a/drivers/leds/ledtrig-cpu.c
+++ b/drivers/leds/ledtrig-cpu.c
@@ -33,8 +33,6 @@
struct led_trigger_cpu {
char name[MAX_NAME_LEN];
struct led_trigger *_trig;
- struct mutex lock;
- int lock_is_inited;
};
static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
@@ -50,12 +48,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
{
struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
- /* mutex lock should be initialized before calling mutex_call() */
- if (!trig->lock_is_inited)
- return;
-
- mutex_lock(&trig->lock);
-
/* Locate the correct CPU LED */
switch (ledevt) {
case CPU_LED_IDLE_END:
@@ -75,8 +67,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
/* Will leave the LED as it is */
break;
}
-
- mutex_unlock(&trig->lock);
}
EXPORT_SYMBOL(ledtrig_cpu);
@@ -117,14 +107,9 @@ static int __init ledtrig_cpu_init(void)
for_each_possible_cpu(cpu) {
struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
- mutex_init(&trig->lock);
-
snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
- mutex_lock(&trig->lock);
led_trigger_register_simple(trig->name, &trig->_trig);
- trig->lock_is_inited = 1;
- mutex_unlock(&trig->lock);
}
register_syscore_ops(&ledtrig_cpu_syscore_ops);
@@ -142,15 +127,9 @@ static void __exit ledtrig_cpu_exit(void)
for_each_possible_cpu(cpu) {
struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
- mutex_lock(&trig->lock);
-
led_trigger_unregister_simple(trig->_trig);
trig->_trig = NULL;
memset(trig->name, 0, MAX_NAME_LEN);
- trig->lock_is_inited = 0;
-
- mutex_unlock(&trig->lock);
- mutex_destroy(&trig->lock);
}
unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 45135f69509..5e7dc772f5d 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -315,8 +315,11 @@ static int run(struct mddev *mddev)
}
conf->nfaults = 0;
- rdev_for_each(rdev, mddev)
+ rdev_for_each(rdev, mddev) {
conf->rdev = rdev;
+ disk_stack_limits(mddev->gendisk, rdev->bdev,
+ rdev->data_offset << 9);
+ }
md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
mddev->private = conf;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 8034fbd6190..636bae0405e 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
|| disk_idx < 0)
continue;
if (test_bit(Replacement, &rdev->flags))
- disk = conf->mirrors + conf->raid_disks + disk_idx;
+ disk = conf->mirrors + mddev->raid_disks + disk_idx;
else
disk = conf->mirrors + disk_idx;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 906ccbd0f7d..d1295aff417 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1783,7 +1783,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
clear_bit(Unmerged, &rdev->flags);
}
md_integrity_add_rdev(rdev, mddev);
- if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+ if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
print_conf(conf);
@@ -3613,11 +3613,14 @@ static int run(struct mddev *mddev)
discard_supported = true;
}
- if (discard_supported)
- queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
- else
- queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-
+ if (mddev->queue) {
+ if (discard_supported)
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+ mddev->queue);
+ else
+ queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD,
+ mddev->queue);
+ }
/* need to check that every block has at least one working mirror */
if (!enough(conf, -1)) {
printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index a3b1a34c896..4b1becc86e5 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -45,8 +45,8 @@
#include <media/v4l2-ioctl.h>
#include <plat/cpu.h>
-#include <plat/dma.h>
-#include <plat/vrfb.h>
+#include <plat-omap/dma-omap.h>
+#include <video/omapvrfb.h>
#include <video/omapdss.h>
#include "omap_voutlib.h"
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c
index 4be26abf6ce..8340445a0ee 100644
--- a/drivers/media/platform/omap/omap_vout_vrfb.c
+++ b/drivers/media/platform/omap/omap_vout_vrfb.c
@@ -16,12 +16,14 @@
#include <media/videobuf-dma-contig.h>
#include <media/v4l2-device.h>
-#include <plat/dma.h>
-#include <plat/vrfb.h>
+#include <plat-omap/dma-omap.h>
+#include <video/omapvrfb.h>
#include "omap_voutdef.h"
#include "omap_voutlib.h"
+#define OMAP_DMA_NO_DEVICE 0
+
/*
* Function for allocating video buffers
*/
diff --git a/drivers/media/platform/omap/omap_voutdef.h b/drivers/media/platform/omap/omap_voutdef.h
index 27a95d23b91..9ccfe1f475a 100644
--- a/drivers/media/platform/omap/omap_voutdef.h
+++ b/drivers/media/platform/omap/omap_voutdef.h
@@ -12,7 +12,7 @@
#define OMAP_VOUTDEF_H
#include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#define YUYV_BPP 2
#define RGB565_BPP 2
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c
index d1a8dee5e1c..e7f9c4292cc 100644
--- a/drivers/media/platform/omap3isp/isphist.c
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -34,6 +34,8 @@
#include "ispreg.h"
#include "isphist.h"
+#define OMAP24XX_DMA_NO_DEVICE 0
+
#define HIST_CONFIG_DMA 1
#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index a6fe653eb23..40f87cdd799 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -30,7 +30,7 @@
#include <linux/types.h>
#include <linux/omap3isp.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <media/v4l2-event.h>
#include "isp.h"
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index a0b737fecf1..5bd40e6870c 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -36,7 +36,6 @@
#include <media/v4l2-ioctl.h>
#include <plat/iommu.h>
#include <plat/iovmm.h>
-#include <plat/omap-pm.h>
#include "ispvideo.h"
#include "isp.h"
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index 9fd9d1c5b21..e575ae82771 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -41,7 +41,6 @@
#include <linux/videodev2.h>
#include <linux/platform_data/camera-mx2.h>
-#include <mach/hardware.h>
#include <asm/dma.h>
@@ -121,11 +120,13 @@
#define CSICR1 0x00
#define CSICR2 0x04
-#define CSISR (cpu_is_mx27() ? 0x08 : 0x18)
+#define CSISR_IMX25 0x18
+#define CSISR_IMX27 0x08
#define CSISTATFIFO 0x0c
#define CSIRFIFO 0x10
#define CSIRXCNT 0x14
-#define CSICR3 (cpu_is_mx27() ? 0x1C : 0x08)
+#define CSICR3_IMX25 0x08
+#define CSICR3_IMX27 0x1c
#define CSIDMASA_STATFIFO 0x20
#define CSIDMATA_STATFIFO 0x24
#define CSIDMASA_FB1 0x28
@@ -268,6 +269,11 @@ struct mx2_buffer {
struct mx2_buf_internal internal;
};
+enum mx2_camera_type {
+ IMX25_CAMERA,
+ IMX27_CAMERA,
+};
+
struct mx2_camera_dev {
struct device *dev;
struct soc_camera_host soc_host;
@@ -291,6 +297,9 @@ struct mx2_camera_dev {
struct mx2_buffer *fb2_active;
u32 csicr1;
+ u32 reg_csisr;
+ u32 reg_csicr3;
+ enum mx2_camera_type devtype;
struct mx2_buf_internal buf_discard[2];
void *discard_buffer;
@@ -303,6 +312,29 @@ struct mx2_camera_dev {
struct vb2_alloc_ctx *alloc_ctx;
};
+static struct platform_device_id mx2_camera_devtype[] = {
+ {
+ .name = "imx25-camera",
+ .driver_data = IMX25_CAMERA,
+ }, {
+ .name = "imx27-camera",
+ .driver_data = IMX27_CAMERA,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, mx2_camera_devtype);
+
+static inline int is_imx25_camera(struct mx2_camera_dev *pcdev)
+{
+ return pcdev->devtype == IMX25_CAMERA;
+}
+
+static inline int is_imx27_camera(struct mx2_camera_dev *pcdev)
+{
+ return pcdev->devtype == IMX27_CAMERA;
+}
+
static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf)
{
return container_of(int_buf, struct mx2_buffer, internal);
@@ -434,9 +466,9 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
clk_disable_unprepare(pcdev->clk_csi);
writel(0, pcdev->base_csi + CSICR1);
- if (cpu_is_mx27()) {
+ if (is_imx27_camera(pcdev)) {
writel(0, pcdev->base_emma + PRP_CNTL);
- } else if (cpu_is_mx25()) {
+ } else if (is_imx25_camera(pcdev)) {
spin_lock_irqsave(&pcdev->lock, flags);
pcdev->fb1_active = NULL;
pcdev->fb2_active = NULL;
@@ -466,7 +498,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
csicr1 = CSICR1_MCLKEN;
- if (cpu_is_mx27())
+ if (is_imx27_camera(pcdev))
csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
CSICR1_RXFF_LEVEL(0);
@@ -542,7 +574,7 @@ out:
static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
{
struct mx2_camera_dev *pcdev = data;
- u32 status = readl(pcdev->base_csi + CSISR);
+ u32 status = readl(pcdev->base_csi + pcdev->reg_csisr);
if (status & CSISR_DMA_TSF_FB1_INT)
mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE);
@@ -551,7 +583,7 @@ static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
/* FIXME: handle CSISR_RFF_OR_INT */
- writel(status, pcdev->base_csi + CSISR);
+ writel(status, pcdev->base_csi + pcdev->reg_csisr);
return IRQ_HANDLED;
}
@@ -636,7 +668,7 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
buf->state = MX2_STATE_QUEUED;
list_add_tail(&buf->internal.queue, &pcdev->capture);
- if (cpu_is_mx25()) {
+ if (is_imx25_camera(pcdev)) {
u32 csicr3, dma_inten = 0;
if (pcdev->fb1_active == NULL) {
@@ -655,20 +687,20 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
list_del(&buf->internal.queue);
buf->state = MX2_STATE_ACTIVE;
- csicr3 = readl(pcdev->base_csi + CSICR3);
+ csicr3 = readl(pcdev->base_csi + pcdev->reg_csicr3);
/* Reflash DMA */
writel(csicr3 | CSICR3_DMA_REFLASH_RFF,
- pcdev->base_csi + CSICR3);
+ pcdev->base_csi + pcdev->reg_csicr3);
/* clear & enable interrupts */
- writel(dma_inten, pcdev->base_csi + CSISR);
+ writel(dma_inten, pcdev->base_csi + pcdev->reg_csisr);
pcdev->csicr1 |= dma_inten;
writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
/* enable DMA */
csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1);
- writel(csicr3, pcdev->base_csi + CSICR3);
+ writel(csicr3, pcdev->base_csi + pcdev->reg_csicr3);
}
}
@@ -712,7 +744,7 @@ static void mx2_videobuf_release(struct vb2_buffer *vb)
*/
spin_lock_irqsave(&pcdev->lock, flags);
- if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) {
+ if (is_imx25_camera(pcdev) && buf->state == MX2_STATE_ACTIVE) {
if (pcdev->fb1_active == buf) {
pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN;
writel(0, pcdev->base_csi + CSIDMASA_FB1);
@@ -835,7 +867,7 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
unsigned long phys;
int bytesperline;
- if (cpu_is_mx27()) {
+ if (is_imx27_camera(pcdev)) {
unsigned long flags;
if (count < 2)
return -EINVAL;
@@ -930,7 +962,7 @@ static int mx2_stop_streaming(struct vb2_queue *q)
void *b;
u32 cntl;
- if (cpu_is_mx27()) {
+ if (is_imx27_camera(pcdev)) {
spin_lock_irqsave(&pcdev->lock, flags);
cntl = readl(pcdev->base_emma + PRP_CNTL);
@@ -1082,11 +1114,11 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
if (bytesperline < 0)
return bytesperline;
- if (cpu_is_mx27()) {
+ if (is_imx27_camera(pcdev)) {
ret = mx27_camera_emma_prp_reset(pcdev);
if (ret)
return ret;
- } else if (cpu_is_mx25()) {
+ } else if (is_imx25_camera(pcdev)) {
writel((bytesperline * icd->user_height) >> 2,
pcdev->base_csi + CSIRXCNT);
writel((bytesperline << 16) | icd->user_height,
@@ -1392,7 +1424,7 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
/* FIXME: implement MX27 limits */
/* limit to MX25 hardware capabilities */
- if (cpu_is_mx25()) {
+ if (is_imx25_camera(pcdev)) {
if (xlate->host_fmt->bits_per_sample <= 8)
width_limit = 0xffff * 4;
else
@@ -1726,6 +1758,20 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
goto exit;
}
+ pcdev->devtype = pdev->id_entry->driver_data;
+ switch (pcdev->devtype) {
+ case IMX25_CAMERA:
+ pcdev->reg_csisr = CSISR_IMX25;
+ pcdev->reg_csicr3 = CSICR3_IMX25;
+ break;
+ case IMX27_CAMERA:
+ pcdev->reg_csisr = CSISR_IMX27;
+ pcdev->reg_csicr3 = CSICR3_IMX27;
+ break;
+ default:
+ break;
+ }
+
pcdev->clk_csi = devm_clk_get(&pdev->dev, "ahb");
if (IS_ERR(pcdev->clk_csi)) {
dev_err(&pdev->dev, "Could not get csi clock\n");
@@ -1763,7 +1809,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
pcdev->dev = &pdev->dev;
platform_set_drvdata(pdev, pcdev);
- if (cpu_is_mx25()) {
+ if (is_imx25_camera(pcdev)) {
err = devm_request_irq(&pdev->dev, irq_csi, mx25_camera_irq, 0,
MX2_CAM_DRV_NAME, pcdev);
if (err) {
@@ -1772,7 +1818,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
}
}
- if (cpu_is_mx27()) {
+ if (is_imx27_camera(pcdev)) {
err = mx27_camera_emma_init(pdev);
if (err)
goto exit;
@@ -1789,7 +1835,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
pcdev->soc_host.priv = pcdev;
pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
pcdev->soc_host.nr = pdev->id;
- if (cpu_is_mx25())
+ if (is_imx25_camera(pcdev))
pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE;
pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
@@ -1809,7 +1855,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
exit_free_emma:
vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
eallocctx:
- if (cpu_is_mx27()) {
+ if (is_imx27_camera(pcdev)) {
clk_disable_unprepare(pcdev->clk_emma_ipg);
clk_disable_unprepare(pcdev->clk_emma_ahb);
}
@@ -1827,7 +1873,7 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)
vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
- if (cpu_is_mx27()) {
+ if (is_imx27_camera(pcdev)) {
clk_disable_unprepare(pcdev->clk_emma_ipg);
clk_disable_unprepare(pcdev->clk_emma_ahb);
}
@@ -1841,6 +1887,7 @@ static struct platform_driver mx2_camera_driver = {
.driver = {
.name = MX2_CAM_DRV_NAME,
},
+ .id_table = mx2_camera_devtype,
.remove = __devexit_p(mx2_camera_remove),
};
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index 3557ac97e43..64d39b1b558 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -17,6 +17,7 @@
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/dma/ipu-dma.h>
#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
@@ -24,7 +25,6 @@
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
-#include <mach/ipu.h>
#include <linux/platform_data/camera-mx3.h>
#include <linux/platform_data/dma-imx.h>
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index fa08c7695cc..cae9ce6275e 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -34,12 +34,13 @@
#include <media/videobuf-dma-contig.h>
#include <media/videobuf-dma-sg.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#define DRIVER_NAME "omap1-camera"
#define DRIVER_VERSION "0.0.2"
+#define OMAP_DMA_CAMERA_IF_RX 20
/*
* ---------------------------------------------------------------------------
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 546199e9ccc..82e6c1e282d 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -28,7 +28,6 @@
#include <plat/dmtimer.h>
#include <plat/clock.h>
-#include <plat/omap-pm.h>
#include <media/lirc.h>
#include <media/lirc_dev.h>
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index 55d58998141..998ce8cb306 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -41,11 +41,11 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/slab.h>
+#include <linux/mfd/menelaus.h>
#include <asm/mach/irq.h>
#include <asm/gpio.h>
-#include <plat/menelaus.h>
#define DRIVER_NAME "menelaus"
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 23cec57c02b..cebfe0a68aa 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -26,9 +26,12 @@
#include <linux/spinlock.h>
#include <linux/gpio.h>
#include <plat/cpu.h>
-#include <plat/usb.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/usb-omap.h>
#include <linux/pm_runtime.h>
+#include "omap-usb.h"
+
#define USBHS_DRIVER_NAME "usbhs_omap"
#define OMAP_EHCI_DEVICE "ehci-omap"
#define OMAP_OHCI_DEVICE "ohci-omap3"
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 4b7757b8430..0db0dfa3d08 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -25,8 +25,8 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/err.h>
-#include <plat/usb.h>
#include <linux/pm_runtime.h>
+#include <linux/platform_data/usb-omap.h>
#define USBTLL_DRIVER_NAME "usbhs_tll"
diff --git a/drivers/mfd/omap-usb.h b/drivers/mfd/omap-usb.h
new file mode 100644
index 00000000000..972aa961b06
--- /dev/null
+++ b/drivers/mfd/omap-usb.h
@@ -0,0 +1,2 @@
+extern int omap_tll_enable(void);
+extern int omap_tll_disable(void);
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 660bbc52886..4d50da61816 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
MMC_CAP_CMD23,
};
-static struct dw_mci_drv_data exynos5250_drv_data = {
+static const struct dw_mci_drv_data exynos5250_drv_data = {
.caps = exynos5250_dwmmc_caps,
.init = dw_mci_exynos_priv_init,
.setup_clock = dw_mci_exynos_setup_clock,
@@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = {
static const struct of_device_id dw_mci_exynos_match[] = {
{ .compatible = "samsung,exynos5250-dw-mshc",
- .data = (void *)&exynos5250_drv_data, },
+ .data = &exynos5250_drv_data, },
{},
};
-MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
+MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
int dw_mci_exynos_probe(struct platform_device *pdev)
{
- struct dw_mci_drv_data *drv_data;
+ const struct dw_mci_drv_data *drv_data;
const struct of_device_id *match;
match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index c960ca7ffbe..917936bee5d 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -24,7 +24,7 @@
#include "dw_mmc.h"
int dw_mci_pltfm_register(struct platform_device *pdev,
- struct dw_mci_drv_data *drv_data)
+ const struct dw_mci_drv_data *drv_data)
{
struct dw_mci *host;
struct resource *regs;
@@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
if (!host->regs)
return -ENOMEM;
- if (host->drv_data->init) {
- ret = host->drv_data->init(host);
+ if (drv_data && drv_data->init) {
+ ret = drv_data->init(host);
if (ret)
return ret;
}
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h
index 301f24541fc..2ac37b81de4 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.h
+++ b/drivers/mmc/host/dw_mmc-pltfm.h
@@ -13,7 +13,7 @@
#define _DW_MMC_PLTFM_H_
extern int dw_mci_pltfm_register(struct platform_device *pdev,
- struct dw_mci_drv_data *drv_data);
+ const struct dw_mci_drv_data *drv_data);
extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
extern const struct dev_pm_ops dw_mci_pltfm_pmops;
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index c2828f35c3b..c0667c8af2b 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
{
struct mmc_data *data;
struct dw_mci_slot *slot = mmc_priv(mmc);
+ struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 cmdr;
cmd->error = -EINPROGRESS;
@@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
cmdr |= SDMMC_CMD_DAT_WR;
}
- if (slot->host->drv_data->prepare_command)
- slot->host->drv_data->prepare_command(slot->host, &cmdr);
+ if (drv_data && drv_data->prepare_command)
+ drv_data->prepare_command(slot->host, &cmdr);
return cmdr;
}
@@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)
return 0;
}
-static struct dw_mci_dma_ops dw_mci_idmac_ops = {
+static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
.init = dw_mci_idmac_init,
.start = dw_mci_idmac_start_dma,
.stop = dw_mci_idmac_stop_dma,
@@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
+ struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 regs;
/* set default 1 bit mode */
@@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
slot->clock = ios->clock;
}
- if (slot->host->drv_data->set_ios)
- slot->host->drv_data->set_ios(slot->host, ios);
+ if (drv_data && drv_data->set_ios)
+ drv_data->set_ios(slot->host, ios);
switch (ios->power_mode) {
case MMC_POWER_UP:
@@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
{
struct mmc_host *mmc;
struct dw_mci_slot *slot;
+ struct dw_mci_drv_data *drv_data = host->drv_data;
int ctrl_id, ret;
u8 bus_width;
@@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
} else {
ctrl_id = to_platform_device(host->dev)->id;
}
- if (host->drv_data && host->drv_data->caps)
- mmc->caps |= host->drv_data->caps[ctrl_id];
+ if (drv_data && drv_data->caps)
+ mmc->caps |= drv_data->caps[ctrl_id];
if (host->pdata->caps2)
mmc->caps2 = host->pdata->caps2;
@@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
else
bus_width = 1;
- if (host->drv_data->setup_bus) {
+ if (drv_data && drv_data->setup_bus) {
struct device_node *slot_np;
slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
- ret = host->drv_data->setup_bus(host, slot_np, bus_width);
+ ret = drv_data->setup_bus(host, slot_np, bus_width);
if (ret)
goto err_setup_bus;
}
@@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
/* Determine which DMA interface to use */
#ifdef CONFIG_MMC_DW_IDMAC
host->dma_ops = &dw_mci_idmac_ops;
- dev_info(&host->dev, "Using internal DMA controller.\n");
+ dev_info(host->dev, "Using internal DMA controller.\n");
#endif
if (!host->dma_ops)
@@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
struct dw_mci_board *pdata;
struct device *dev = host->dev;
struct device_node *np = dev->of_node;
+ struct dw_mci_drv_data *drv_data = host->drv_data;
int idx, ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
- if (host->drv_data->parse_dt) {
- ret = host->drv_data->parse_dt(host);
+ if (drv_data && drv_data->parse_dt) {
+ ret = drv_data->parse_dt(host);
if (ret)
return ERR_PTR(ret);
}
@@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
int dw_mci_probe(struct dw_mci *host)
{
+ struct dw_mci_drv_data *drv_data = host->drv_data;
int width, i, ret = 0;
u32 fifo_size;
int init_slots = 0;
@@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)
else
host->bus_hz = clk_get_rate(host->ciu_clk);
- if (host->drv_data->setup_clock) {
- ret = host->drv_data->setup_clock(host);
+ if (drv_data && drv_data->setup_clock) {
+ ret = drv_data->setup_clock(host);
if (ret) {
dev_err(host->dev,
"implementation specific clock setup failed\n");
@@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host)
else
host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
+ /*
+ * Enable interrupts for command done, data over, data empty, card det,
+ * receive ready and error such as transmit, receive timeout, crc error
+ */
+ mci_writel(host, RINTSTS, 0xFFFFFFFF);
+ mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+ SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+ DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+ mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
+
+ dev_info(host->dev, "DW MMC controller at irq %d, "
+ "%d bit host data width, "
+ "%u deep fifo\n",
+ host->irq, width, fifo_size);
+
/* We need at least one slot to succeed */
for (i = 0; i < host->num_slots; i++) {
ret = dw_mci_init_slot(host, i);
@@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host)
else
host->data_offset = DATA_240A_OFFSET;
- /*
- * Enable interrupts for command done, data over, data empty, card det,
- * receive ready and error such as transmit, receive timeout, crc error
- */
- mci_writel(host, RINTSTS, 0xFFFFFFFF);
- mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
- SDMMC_INT_TXDR | SDMMC_INT_RXDR |
- DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
- mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
-
- dev_info(host->dev, "DW MMC controller at irq %d, "
- "%d bit host data width, "
- "%u deep fifo\n",
- host->irq, width, fifo_size);
if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 565c2e4fac7..477f63bad52 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -41,7 +41,6 @@
#include <linux/platform_data/mmc-mxcmmc.h>
#include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
#define DRIVER_NAME "mxc-mmc"
#define MXCMCI_TIMEOUT_MS 10000
@@ -113,6 +112,11 @@
#define INT_WRITE_OP_DONE_EN (1 << 1)
#define INT_READ_OP_EN (1 << 0)
+enum mxcmci_type {
+ IMX21_MMC,
+ IMX31_MMC,
+};
+
struct mxcmci_host {
struct mmc_host *mmc;
struct resource *res;
@@ -153,7 +157,26 @@ struct mxcmci_host {
struct imx_dma_data dma_data;
struct timer_list watchdog;
+ enum mxcmci_type devtype;
+};
+
+static struct platform_device_id mxcmci_devtype[] = {
+ {
+ .name = "imx21-mmc",
+ .driver_data = IMX21_MMC,
+ }, {
+ .name = "imx31-mmc",
+ .driver_data = IMX31_MMC,
+ }, {
+ /* sentinel */
+ }
};
+MODULE_DEVICE_TABLE(platform, mxcmci_devtype);
+
+static inline int is_imx31_mmc(struct mxcmci_host *host)
+{
+ return host->devtype == IMX31_MMC;
+}
static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -843,6 +866,8 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
{
+ struct mxcmci_host *mxcmci = mmc_priv(host);
+
/*
* MX3 SoCs have a silicon bug which corrupts CRC calculation of
* multi-block transfers when connected SDIO peripheral doesn't
@@ -850,7 +875,7 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
* One way to prevent this is to only allow 1-bit transfers.
*/
- if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO)
+ if (is_imx31_mmc(mxcmci) && card->type == MMC_TYPE_SDIO)
host->caps &= ~MMC_CAP_4_BIT_DATA;
else
host->caps |= MMC_CAP_4_BIT_DATA;
@@ -948,6 +973,7 @@ static int mxcmci_probe(struct platform_device *pdev)
host->mmc = mmc;
host->pdata = pdev->dev.platform_data;
+ host->devtype = pdev->id_entry->driver_data;
spin_lock_init(&host->lock);
mxcmci_init_ocr(host);
@@ -1120,6 +1146,7 @@ static const struct dev_pm_ops mxcmci_pm_ops = {
static struct platform_driver mxcmci_driver = {
.probe = mxcmci_probe,
.remove = mxcmci_remove,
+ .id_table = mxcmci_devtype,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
@@ -1134,4 +1161,4 @@ module_platform_driver(mxcmci_driver);
MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx-mmc");
+MODULE_ALIAS("platform:mxc-mmc");
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 48ad361613e..ae115c01283 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -28,9 +28,8 @@
#include <linux/clk.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/platform_data/mmc-omap.h>
-#include <plat/mmc.h>
-#include <plat/dma.h>
#define OMAP_MMC_REG_CMD 0x00
#define OMAP_MMC_REG_ARGL 0x01
@@ -72,6 +71,13 @@
#define OMAP_MMC_STAT_CARD_BUSY (1 << 2)
#define OMAP_MMC_STAT_END_OF_CMD (1 << 0)
+#define mmc_omap7xx() (host->features & MMC_OMAP7XX)
+#define mmc_omap15xx() (host->features & MMC_OMAP15XX)
+#define mmc_omap16xx() (host->features & MMC_OMAP16XX)
+#define MMC_OMAP1_MASK (MMC_OMAP7XX | MMC_OMAP15XX | MMC_OMAP16XX)
+#define mmc_omap1() (host->features & MMC_OMAP1_MASK)
+#define mmc_omap2() (!mmc_omap1())
+
#define OMAP_MMC_REG(host, reg) (OMAP_MMC_REG_##reg << (host)->reg_shift)
#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG(host, reg))
#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG(host, reg))
@@ -84,6 +90,16 @@
#define OMAP_MMC_CMDTYPE_AC 2
#define OMAP_MMC_CMDTYPE_ADTC 3
+#define OMAP_DMA_MMC_TX 21
+#define OMAP_DMA_MMC_RX 22
+#define OMAP_DMA_MMC2_TX 54
+#define OMAP_DMA_MMC2_RX 55
+
+#define OMAP24XX_DMA_MMC2_TX 47
+#define OMAP24XX_DMA_MMC2_RX 48
+#define OMAP24XX_DMA_MMC1_TX 61
+#define OMAP24XX_DMA_MMC1_RX 62
+
#define DRIVER_NAME "mmci-omap"
@@ -147,6 +163,7 @@ struct mmc_omap_host {
u32 buffer_bytes_left;
u32 total_bytes_left;
+ unsigned features;
unsigned use_dma:1;
unsigned brs_received:1, dma_done:1;
unsigned dma_in_use:1;
@@ -988,7 +1005,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
* blocksize is at least that large. Blocksize is
* usually 512 bytes; but not for some SD reads.
*/
- burst = cpu_is_omap15xx() ? 32 : 64;
+ burst = mmc_omap15xx() ? 32 : 64;
if (burst > data->blksz)
burst = data->blksz;
@@ -1104,8 +1121,7 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
if (slot->pdata->set_power != NULL)
slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
vdd);
-
- if (cpu_is_omap24xx()) {
+ if (mmc_omap2()) {
u16 w;
if (power_on) {
@@ -1239,7 +1255,7 @@ static int __devinit mmc_omap_new_slot(struct mmc_omap_host *host, int id)
mmc->ops = &mmc_omap_ops;
mmc->f_min = 400000;
- if (cpu_class_is_omap2())
+ if (mmc_omap2())
mmc->f_max = 48000000;
else
mmc->f_max = 24000000;
@@ -1359,6 +1375,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
init_waitqueue_head(&host->slot_wq);
host->pdata = pdata;
+ host->features = host->pdata->slots[0].features;
host->dev = &pdev->dev;
platform_set_drvdata(pdev, host);
@@ -1391,7 +1408,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
host->dma_tx_burst = -1;
host->dma_rx_burst = -1;
- if (cpu_is_omap24xx())
+ if (mmc_omap2())
sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX;
else
sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX;
@@ -1407,7 +1424,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n",
sig);
#endif
- if (cpu_is_omap24xx())
+ if (mmc_omap2())
sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX;
else
sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX;
@@ -1435,7 +1452,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
}
host->nr_slots = pdata->nr_slots;
- host->reg_shift = (cpu_is_omap7xx() ? 1 : 2);
+ host->reg_shift = (mmc_omap7xx() ? 1 : 2);
host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0);
if (!host->mmc_omap_wq)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 54bfd0cc106..e7c185233b1 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -38,9 +38,7 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
-#include <mach/hardware.h>
-#include <plat/mmc.h>
-#include <plat/cpu.h>
+#include <linux/platform_data/mmc-omap.h>
/* OMAP HSMMC Host Controller Registers */
#define OMAP_HSMMC_SYSSTATUS 0x0014
@@ -178,7 +176,8 @@ struct omap_hsmmc_host {
static int omap_hsmmc_card_detect(struct device *dev, int slot)
{
- struct omap_mmc_platform_data *mmc = dev->platform_data;
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+ struct omap_mmc_platform_data *mmc = host->pdata;
/* NOTE: assumes card detect signal is active-low */
return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -186,7 +185,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot)
static int omap_hsmmc_get_wp(struct device *dev, int slot)
{
- struct omap_mmc_platform_data *mmc = dev->platform_data;
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+ struct omap_mmc_platform_data *mmc = host->pdata;
/* NOTE: assumes write protect signal is active-high */
return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
@@ -194,7 +194,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot)
static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
{
- struct omap_mmc_platform_data *mmc = dev->platform_data;
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+ struct omap_mmc_platform_data *mmc = host->pdata;
/* NOTE: assumes card detect signal is active-low */
return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -204,7 +205,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
{
- struct omap_mmc_platform_data *mmc = dev->platform_data;
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+ struct omap_mmc_platform_data *mmc = host->pdata;
disable_irq(mmc->slots[0].card_detect_irq);
return 0;
@@ -212,7 +214,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
{
- struct omap_mmc_platform_data *mmc = dev->platform_data;
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+ struct omap_mmc_platform_data *mmc = host->pdata;
enable_irq(mmc->slots[0].card_detect_irq);
return 0;
@@ -2009,9 +2012,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
clk_put(host->dbclk);
}
- mmc_free_host(host->mmc);
+ omap_hsmmc_gpio_free(host->pdata);
iounmap(host->base);
- omap_hsmmc_gpio_free(pdev->dev.platform_data);
+ mmc_free_host(host->mmc);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 90140eb03e3..8fd50a21103 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)
struct sdhci_dove_priv *priv;
int ret;
- ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
- if (ret)
- goto sdhci_dove_register_fail;
-
priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "unable to allocate private data");
- ret = -ENOMEM;
- goto sdhci_dove_allocate_fail;
+ return -ENOMEM;
}
+ priv->clk = clk_get(&pdev->dev, NULL);
+ if (!IS_ERR(priv->clk))
+ clk_prepare_enable(priv->clk);
+
+ ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+ if (ret)
+ goto sdhci_dove_register_fail;
+
host = platform_get_drvdata(pdev);
pltfm_host = sdhci_priv(host);
pltfm_host->priv = priv;
- priv->clk = clk_get(&pdev->dev, NULL);
- if (!IS_ERR(priv->clk))
- clk_prepare_enable(priv->clk);
return 0;
-sdhci_dove_allocate_fail:
- sdhci_pltfm_unregister(pdev);
sdhci_dove_register_fail:
+ if (!IS_ERR(priv->clk)) {
+ clk_disable_unprepare(priv->clk);
+ clk_put(priv->clk);
+ }
return ret;
}
@@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_dove_priv *priv = pltfm_host->priv;
- if (priv->clk) {
- if (!IS_ERR(priv->clk)) {
- clk_disable_unprepare(priv->clk);
- clk_put(priv->clk);
- }
- devm_kfree(&pdev->dev, priv->clk);
+ sdhci_pltfm_unregister(pdev);
+
+ if (!IS_ERR(priv->clk)) {
+ clk_disable_unprepare(priv->clk);
+ clk_put(priv->clk);
}
- return sdhci_pltfm_unregister(pdev);
+ return 0;
}
static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index ae5fcbfa1ee..63d219f57ca 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host)
}
#endif
+static void esdhc_of_platform_init(struct sdhci_host *host)
+{
+ u32 vvn;
+
+ vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+ vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+ if (vvn == VENDOR_V_22)
+ host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+}
+
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl,
.read_w = esdhc_readw,
@@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.enable_dma = esdhc_of_enable_dma,
.get_max_clock = esdhc_of_get_max_clock,
.get_min_clock = esdhc_of_get_min_clock,
+ .platform_init = esdhc_of_platform_init,
#ifdef CONFIG_PM
.platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume,
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 4bb74b042a0..04936f353ce 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
return ERR_PTR(-ENODEV);
}
- if (pci_resource_len(pdev, bar) != 0x100) {
+ if (pci_resource_len(pdev, bar) < 0x100) {
dev_err(&pdev->dev, "Invalid iomem size. You may "
"experience problems.\n");
}
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 65551a9709c..27164457f86 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
goto err_remap;
}
+ /*
+ * Some platforms need to probe the controller to be able to
+ * determine which caps should be used.
+ */
+ if (host->ops && host->ops->platform_init)
+ host->ops->platform_init(host);
+
platform_set_drvdata(pdev, host);
return host;
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 2903949594c..a54dd5d7a5f 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
if (ourhost->cur_clk != best_src) {
struct clk *clk = ourhost->clk_bus[best_src];
- clk_enable(clk);
- clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
+ clk_prepare_enable(clk);
+ clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
/* turn clock off to card before changing clock source */
writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
@@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
}
/* enable the local io clock and keep it running for the moment. */
- clk_enable(sc->clk_io);
+ clk_prepare_enable(sc->clk_io);
for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
struct clk *clk;
@@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
}
#ifndef CONFIG_PM_RUNTIME
- clk_enable(sc->clk_bus[sc->cur_clk]);
+ clk_prepare_enable(sc->clk_bus[sc->cur_clk]);
#endif
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
sdhci_s3c_setup_card_detect_gpio(sc);
#ifdef CONFIG_PM_RUNTIME
- clk_disable(sc->clk_io);
+ if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+ clk_disable_unprepare(sc->clk_io);
#endif
return 0;
err_req_regs:
#ifndef CONFIG_PM_RUNTIME
- clk_disable(sc->clk_bus[sc->cur_clk]);
+ clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) {
@@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
}
err_no_busclks:
- clk_disable(sc->clk_io);
+ clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io);
err_io_clk:
@@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
gpio_free(sc->ext_cd_gpio);
#ifdef CONFIG_PM_RUNTIME
- clk_enable(sc->clk_io);
+ if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+ clk_prepare_enable(sc->clk_io);
#endif
sdhci_remove_host(host, 1);
@@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
#ifndef CONFIG_PM_RUNTIME
- clk_disable(sc->clk_bus[sc->cur_clk]);
+ clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
#endif
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) {
clk_put(sc->clk_bus[ptr]);
}
}
- clk_disable(sc->clk_io);
+ clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io);
if (pdev->dev.of_node) {
@@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)
ret = sdhci_runtime_suspend_host(host);
- clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
- clk_disable(busclk);
+ clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
+ clk_disable_unprepare(busclk);
return ret;
}
@@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
struct clk *busclk = ourhost->clk_io;
int ret;
- clk_enable(busclk);
- clk_enable(ourhost->clk_bus[ourhost->cur_clk]);
+ clk_prepare_enable(busclk);
+ clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
ret = sdhci_runtime_resume_host(host);
return ret;
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7922adb4238..c7851c0aabc 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
*/
if ((host->flags & SDHCI_NEEDS_RETUNING) &&
!(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
- /* eMMC uses cmd21 while sd and sdio use cmd19 */
- tuning_opcode = mmc->card->type == MMC_TYPE_MMC ?
- MMC_SEND_TUNING_BLOCK_HS200 :
- MMC_SEND_TUNING_BLOCK;
- spin_unlock_irqrestore(&host->lock, flags);
- sdhci_execute_tuning(mmc, tuning_opcode);
- spin_lock_irqsave(&host->lock, flags);
-
- /* Restore original mmc_request structure */
- host->mrq = mrq;
+ if (mmc->card) {
+ /* eMMC uses cmd21 but sd and sdio use cmd19 */
+ tuning_opcode =
+ mmc->card->type == MMC_TYPE_MMC ?
+ MMC_SEND_TUNING_BLOCK_HS200 :
+ MMC_SEND_TUNING_BLOCK;
+ spin_unlock_irqrestore(&host->lock, flags);
+ sdhci_execute_tuning(mmc, tuning_opcode);
+ spin_lock_irqsave(&host->lock, flags);
+
+ /* Restore original mmc_request structure */
+ host->mrq = mrq;
+ }
}
if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
@@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host)
if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
mmc->caps |= MMC_CAP_4_BIT_DATA;
+ if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
+ mmc->caps &= ~MMC_CAP_CMD23;
+
if (caps[0] & SDHCI_CAN_DO_HISPD)
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
@@ -2846,9 +2852,12 @@ int sdhci_add_host(struct sdhci_host *host)
/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
- if (IS_ERR(host->vqmmc)) {
- pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc));
- host->vqmmc = NULL;
+ if (IS_ERR_OR_NULL(host->vqmmc)) {
+ if (PTR_ERR(host->vqmmc) < 0) {
+ pr_info("%s: no vqmmc regulator found\n",
+ mmc_hostname(mmc));
+ host->vqmmc = NULL;
+ }
}
else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
regulator_enable(host->vqmmc);
@@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host)
ocr_avail = 0;
host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
- if (IS_ERR(host->vmmc)) {
- pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
- host->vmmc = NULL;
+ if (IS_ERR_OR_NULL(host->vmmc)) {
+ if (PTR_ERR(host->vmmc) < 0) {
+ pr_info("%s: no vmmc regulator found\n",
+ mmc_hostname(mmc));
+ host->vmmc = NULL;
+ }
} else
regulator_enable(host->vmmc);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 97653ea8942..71a4a7ed46c 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -278,6 +278,7 @@ struct sdhci_ops {
void (*hw_reset)(struct sdhci_host *host);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
+ void (*platform_init)(struct sdhci_host *host);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 11d2bc3b51d..d25bc97dc5c 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
+ clk_disable(host->hclk);
mmc_free_host(host->mmc);
pm_runtime_put_sync(&pdev->dev);
- clk_disable(host->hclk);
pm_runtime_disable(&pdev->dev);
return 0;
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 72e31d86030..022dcdc256f 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -37,15 +37,9 @@
#include <asm/mach/flash.h>
#include <linux/platform_data/mtd-mxc_nand.h>
-#include <mach/hardware.h>
#define DRIVER_NAME "mxc_nand"
-#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
-#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
-#define nfc_is_v3_2a() cpu_is_mx51()
-#define nfc_is_v3_2b() cpu_is_mx53()
-
/* Addresses for NFC registers */
#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
@@ -1283,6 +1277,53 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
.ppb_shift = 8,
};
+static inline int is_imx21_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx21_nand_devtype_data;
+}
+
+static inline int is_imx27_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx27_nand_devtype_data;
+}
+
+static inline int is_imx25_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx25_nand_devtype_data;
+}
+
+static inline int is_imx51_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx51_nand_devtype_data;
+}
+
+static inline int is_imx53_nfc(struct mxc_nand_host *host)
+{
+ return host->devtype_data == &imx53_nand_devtype_data;
+}
+
+static struct platform_device_id mxcnd_devtype[] = {
+ {
+ .name = "imx21-nand",
+ .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
+ }, {
+ .name = "imx27-nand",
+ .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
+ }, {
+ .name = "imx25-nand",
+ .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
+ }, {
+ .name = "imx51-nand",
+ .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
+ }, {
+ .name = "imx53-nand",
+ .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
+
#ifdef CONFIG_OF_MTD
static const struct of_device_id mxcnd_dt_ids[] = {
{
@@ -1337,32 +1378,6 @@ static int __init mxcnd_probe_dt(struct mxc_nand_host *host)
}
#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_2a()) {
- host->devtype_data = &imx51_nand_devtype_data;
- } else if (nfc_is_v3_2b()) {
- host->devtype_data = &imx53_nand_devtype_data;
- } else
- BUG();
-
- return 0;
-}
-
static int __devinit mxcnd_probe(struct platform_device *pdev)
{
struct nand_chip *this;
@@ -1404,8 +1419,16 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
return PTR_ERR(host->clk);
err = mxcnd_probe_dt(host);
- if (err > 0)
- err = mxcnd_probe_pdata(host);
+ if (err > 0) {
+ struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+ if (pdata) {
+ host->pdata = *pdata;
+ host->devtype_data = (struct mxc_nand_devtype_data *)
+ pdev->id_entry->driver_data;
+ } else {
+ err = -ENODEV;
+ }
+ }
if (err < 0)
return err;
@@ -1494,7 +1517,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
}
/* first scan to find the device and get the page size */
- if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
+ if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
err = -ENXIO;
goto escan;
}
@@ -1508,7 +1531,7 @@ static int __devinit mxcnd_probe(struct platform_device *pdev)
this->ecc.layout = host->devtype_data->ecclayout_4k;
if (this->ecc.mode == NAND_ECC_HW) {
- if (nfc_is_v1())
+ if (is_imx21_nfc(host) || is_imx27_nfc(host))
this->ecc.strength = 1;
else
this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
@@ -1555,6 +1578,7 @@ static struct platform_driver mxcnd_driver = {
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(mxcnd_dt_ids),
},
+ .id_table = mxcnd_devtype,
.probe = mxcnd_probe,
.remove = __devexit_p(mxcnd_remove),
};
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5b313862064..5c8978e9024 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -27,8 +27,7 @@
#include <linux/bch.h>
#endif
-#include <plat/dma.h>
-#include <plat/gpmc.h>
+#include <plat-omap/dma-omap.h>
#include <linux/platform_data/mtd-nand-omap2.h>
#define DRIVER_NAME "omap2-nand"
@@ -106,10 +105,18 @@
#define CS_MASK 0x7
#define ENABLE_PREFETCH (0x1 << 7)
#define DMA_MPU_MODE_SHIFT 2
+#define ECCSIZE0_SHIFT 12
#define ECCSIZE1_SHIFT 22
#define ECC1RESULTSIZE 0x1
#define ECCCLEAR 0x100
#define ECC1 0x1
+#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
+#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
+#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
+#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
+#define STATUS_BUFF_EMPTY 0x00000001
+
+#define OMAP24XX_DMA_GPMC 4
/* oob info generated runtime depending on ecc algorithm and layout selected */
static struct nand_ecclayout omap_oobinfo;
@@ -269,7 +276,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
/* wait until buffer is available for write */
do {
status = readl(info->reg.gpmc_status) &
- GPMC_STATUS_BUFF_EMPTY;
+ STATUS_BUFF_EMPTY;
} while (!status);
}
}
@@ -307,7 +314,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
/* wait until buffer is available for write */
do {
status = readl(info->reg.gpmc_status) &
- GPMC_STATUS_BUFF_EMPTY;
+ STATUS_BUFF_EMPTY;
} while (!status);
}
}
@@ -348,7 +355,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
} else {
do {
r_count = readl(info->reg.gpmc_prefetch_status);
- r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
+ r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
r_count = r_count >> 2;
ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
@@ -395,7 +402,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
} else {
while (len) {
w_count = readl(info->reg.gpmc_prefetch_status);
- w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
+ w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
w_count = w_count >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -407,7 +414,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
do {
cpu_relax();
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
} while (val && (tim++ < limit));
/* disable and stop the PFPW engine */
@@ -493,7 +500,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
do {
cpu_relax();
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
} while (val && (tim++ < limit));
/* disable and stop the PFPW engine */
@@ -556,7 +563,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
u32 bytes;
bytes = readl(info->reg.gpmc_prefetch_status);
- bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
+ bytes = PREFETCH_STATUS_FIFO_CNT(bytes);
bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */
if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
if (this_irq == info->gpmc_irq_count)
@@ -682,7 +689,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
do {
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
cpu_relax();
} while (val && (tim++ < limit));
@@ -996,7 +1003,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
cond_resched();
}
- status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+ status = readb(info->reg.gpmc_nand_data);
return status;
}
@@ -1029,19 +1036,45 @@ static int omap_dev_ready(struct mtd_info *mtd)
static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
{
int nerrors;
- unsigned int dev_width;
+ unsigned int dev_width, nsectors;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
struct nand_chip *chip = mtd->priv;
+ u32 val;
nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+ nsectors = 1;
/*
* 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);
+
+ writel(ECC1, info->reg.gpmc_ecc_control);
+
+ /*
+ * 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)
+ */
+ val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
+ writel(val, info->reg.gpmc_ecc_size_config);
+
+ /* 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 */
+ (info->gpmc_cs << 1) | /* ECC CS */
+ (0x1)); /* enable ECC */
+
+ writel(val, info->reg.gpmc_ecc_config);
+
+ /* clear ecc and enable bits */
+ writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
}
/**
@@ -1055,7 +1088,32 @@ static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code);
+ unsigned long nsectors, val1, val2;
+ int i;
+
+ nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+ for (i = 0; i < nsectors; i++) {
+
+ /* Read hw-computed remainder */
+ val1 = readl(info->reg.gpmc_bch_result0[i]);
+ val2 = readl(info->reg.gpmc_bch_result1[i]);
+
+ /*
+ * 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_code++ = 0x28 ^ ((val2 >> 12) & 0xFF);
+ *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF);
+ *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
+ *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF);
+ *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF);
+ *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF);
+ *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4);
+ }
+
+ return 0;
}
/**
@@ -1069,7 +1127,39 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code);
+ unsigned long nsectors, val1, val2, val3, val4;
+ int i;
+
+ nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+ for (i = 0; i < nsectors; i++) {
+
+ /* Read hw-computed remainder */
+ val1 = readl(info->reg.gpmc_bch_result0[i]);
+ val2 = readl(info->reg.gpmc_bch_result1[i]);
+ val3 = readl(info->reg.gpmc_bch_result2[i]);
+ val4 = readl(info->reg.gpmc_bch_result3[i]);
+
+ /*
+ * Add constant polynomial to remainder, in order to get an ecc
+ * sequence of 0xFFs for a buffer filled with 0xFFs.
+ */
+ *ecc_code++ = 0xef ^ (val4 & 0xFF);
+ *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF);
+ *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF);
+ *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF);
+ *ecc_code++ = 0xed ^ (val3 & 0xFF);
+ *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF);
+ *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF);
+ *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
+ *ecc_code++ = 0x97 ^ (val2 & 0xFF);
+ *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF);
+ *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
+ *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF);
+ *ecc_code++ = 0xb5 ^ (val1 & 0xFF);
+ }
+
+ return 0;
}
/**
@@ -1125,7 +1215,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
*/
static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
{
- int ret, max_errors;
+ int max_errors;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
#ifdef CONFIG_MTD_NAND_OMAP_BCH8
@@ -1142,11 +1232,6 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
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)
@@ -1513,7 +1598,7 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
iounmap(info->nand.IO_ADDR_R);
- release_mem_region(info->phys_base, NAND_IO_SIZE);
+ release_mem_region(info->phys_base, info->mem_size);
kfree(info);
return 0;
}
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 1961be98517..99f96e19ebe 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -38,12 +38,10 @@
#include <linux/regulator/consumer.h>
#include <asm/mach/flash.h>
-#include <plat/gpmc.h>
#include <linux/platform_data/mtd-onenand-omap2.h>
#include <asm/gpio.h>
-#include <plat/dma.h>
-#include <plat/cpu.h>
+#include <plat-omap/dma-omap.h>
#define DRIVER_NAME "omap2-onenand"
@@ -63,6 +61,7 @@ struct omap2_onenand {
int freq;
int (*setup)(void __iomem *base, int *freq_ptr);
struct regulator *regulator;
+ u8 flags;
};
static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
@@ -155,7 +154,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
syscfg |= ONENAND_SYS_CFG1_IOBE;
write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
- if (cpu_is_omap34xx())
+ if (c->flags & ONENAND_IN_OMAP34XX)
/* Add a delay to let GPIO settle */
syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
}
@@ -446,13 +445,19 @@ out_copy:
#else
-int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
- unsigned char *buffer, int offset,
- size_t count);
+static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ return -ENOSYS;
+}
-int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
- const unsigned char *buffer,
- int offset, size_t count);
+static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count)
+{
+ return -ENOSYS;
+}
#endif
@@ -550,13 +555,19 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
#else
-int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
- unsigned char *buffer, int offset,
- size_t count);
+static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ return -ENOSYS;
+}
-int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
- const unsigned char *buffer,
- int offset, size_t count);
+static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count)
+{
+ return -ENOSYS;
+}
#endif
@@ -639,6 +650,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
init_completion(&c->irq_done);
init_completion(&c->dma_done);
+ c->flags = pdata->flags;
c->gpmc_cs = pdata->cs;
c->gpio_irq = pdata->gpio_irq;
c->dma_channel = pdata->dma_channel;
@@ -729,7 +741,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
this = &c->onenand;
if (c->dma_channel >= 0) {
this->wait = omap2_onenand_wait;
- if (cpu_is_omap34xx()) {
+ if (c->flags & ONENAND_IN_OMAP34XX) {
this->read_bufferram = omap3_onenand_read_bufferram;
this->write_bufferram = omap3_onenand_write_bufferram;
} else {
@@ -803,7 +815,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
}
iounmap(c->onenand.base);
release_mem_region(c->phys_base, c->mem_size);
- gpmc_cs_free(c->gpmc_cs);
kfree(c);
return 0;
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index dc15d248443..ef8d2a080d1 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,
goto out;
}
- sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+ sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
/* check to see if we are clearing primary */
if (!strlen(ifname) || buf[0] == '\n') {
@@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
goto out;
}
- sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+ sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
/* check to see if we are clearing active */
if (!strlen(ifname) || buf[0] == '\n') {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index c65295dded3..6e5bdd1a31d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata)
SHMEM_EEE_ADV_STATUS_SHIFT);
if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) {
DP(BNX2X_MSG_ETHTOOL,
- "Direct manipulation of EEE advertisment is not supported\n");
+ "Direct manipulation of EEE advertisement is not supported\n");
return -EINVAL;
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index e2e45ee5df3..f6cfdc6cf20 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -137,7 +137,16 @@
#define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
#define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
-
+#define LINK_UPDATE_MASK \
+ (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
+ LINK_STATUS_LINK_UP | \
+ LINK_STATUS_PHYSICAL_LINK_FLAG | \
+ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \
+ LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \
+ LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \
+ LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \
+ LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
+ LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
#define SFP_EEPROM_CON_TYPE_ADDR 0x2
#define SFP_EEPROM_CON_TYPE_VAL_LC 0x7
@@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
DEFAULT_PHY_DEV_ADDR);
}
+static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy,
+ struct link_params *params,
+ u32 action)
+{
+ struct bnx2x *bp = params->bp;
+ switch (action) {
+ case PHY_INIT:
+ /* Set correct devad */
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
+ REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
+ phy->def_md_devad);
+ break;
+ }
+}
+
static void bnx2x_xgxs_deassert(struct link_params *params)
{
struct bnx2x *bp = params->bp;
@@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
udelay(500);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
-
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
- REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
- params->phy[INT_PHY].def_md_devad);
+ bnx2x_xgxs_specific_func(&params->phy[INT_PHY], params,
+ PHY_INIT);
}
static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars) {
- u16 val16 = 0, lane, i;
+ u16 lane, i, cl72_ctrl, an_adv = 0;
+ u16 ucode_ver;
struct bnx2x *bp = params->bp;
static struct bnx2x_reg_set reg_set[] = {
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
- {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0},
- {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff},
- {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},
{MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
{MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
@@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
reg_set[i].val);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+ cl72_ctrl &= 0xf8ff;
+ cl72_ctrl |= 0x3800;
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+
/* Check adding advertisement for 1G KX */
if (((vars->line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
(vars->line_speed == SPEED_1000)) {
u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
- val16 |= (1<<5);
+ an_adv |= (1<<5);
/* Enable CL37 1G Parallel Detect */
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1);
@@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
(vars->line_speed == SPEED_10000)) {
/* Check adding advertisement for 10G KR */
- val16 |= (1<<7);
+ an_adv |= (1<<7);
/* Enable 10G Parallel Detect */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
-
+ bnx2x_set_aer_mmd(params, phy);
DP(NETIF_MSG_LINK, "Advertize 10G\n");
}
@@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Advertised speeds */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
- MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+ MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
/* Advertised and set FEC (Forward Error Correction) */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Set KR Autoneg Work-Around flag for Warpcore version older than D108
*/
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
- if (val16 < 0xd108) {
- DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+ MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
+ if (ucode_ver < 0xd108) {
+ DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
+ ucode_ver);
vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
}
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
@@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
struct link_vars *vars)
{
struct bnx2x *bp = params->bp;
- u16 i;
+ u16 val16, i, lane;
static struct bnx2x_reg_set reg_set[] = {
/* Disable Autoneg */
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
- {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
0x3f00},
{MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
{MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
- /* Disable CL36 PCS Tx */
- {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0},
- /* Double Wide Single Data Rate @ pll rate */
- {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},
/* Leave cl72 training enable, needed for KR */
{MDIO_PMA_DEVAD,
MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
@@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
reg_set[i].val);
- /* Leave CL72 enabled */
- bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
- 0x3800);
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ /* Global registers */
+ CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+ MDIO_AER_BLOCK_AER_REG, 0);
+ /* Disable CL36 PCS Tx */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+ val16 &= ~(0x0011 << lane);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+ val16 |= (0x0303 << (lane << 1));
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+ /* Restore AER */
+ bnx2x_set_aer_mmd(params, phy);
/* Set speed via PMA/PMD register */
bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
@@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
struct link_params *params)
{
struct bnx2x *bp = params->bp;
- u16 val16;
+ u16 val16, lane;
bnx2x_sfp_e3_set_transmitter(params, phy, 0);
bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
bnx2x_set_aer_mmd(params, phy);
@@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
MDIO_WC_REG_XGXSBLK1_LANECTRL2,
val16 & 0xff00);
+ lane = bnx2x_get_warpcore_lane(phy, params);
+ /* Disable CL36 PCS Tx */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+ val16 |= (0x11 << lane);
+ if (phy->flags & FLAGS_WC_DUAL_MODE)
+ val16 |= (0x22 << lane);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
+
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+ val16 &= ~(0x0303 << (lane << 1));
+ val16 |= (0x0101 << (lane << 1));
+ if (phy->flags & FLAGS_WC_DUAL_MODE) {
+ val16 &= ~(0x0c0c << (lane << 1));
+ val16 |= (0x0404 << (lane << 1));
+ }
+
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+ /* Restore AER */
+ bnx2x_set_aer_mmd(params, phy);
+
}
static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
@@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,
vars->mac_type = MAC_TYPE_NONE;
/* Update shared memory */
- vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
- LINK_STATUS_LINK_UP |
- LINK_STATUS_PHYSICAL_LINK_FLAG |
- LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
- LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
- LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
- LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK |
- LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
- LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
+ vars->link_status &= ~LINK_UPDATE_MASK;
vars->line_speed = 0;
bnx2x_update_mng(params, vars->link_status);
@@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
u8 active_external_phy = INT_PHY;
vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+ vars->link_status &= ~LINK_UPDATE_MASK;
for (phy_index = INT_PHY; phy_index < params->num_phys;
phy_index++) {
phy_vars[phy_index].flow_ctrl = 0;
@@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
struct link_params *params,
u16 addr, u8 byte_cnt,
- u8 *o_buf)
+ u8 *o_buf, u8 is_init)
{
int rc = 0;
u8 i, j = 0, cnt = 0;
@@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
/* 4 byte aligned address */
addr32 = addr & (~0x3);
do {
- if (cnt == I2C_WA_PWR_ITER) {
+ if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
bnx2x_warpcore_power_module(params, phy, 0);
/* Note that 100us are not enough here */
- usleep_range(1000,1000);
+ usleep_range(1000, 2000);
bnx2x_warpcore_power_module(params, phy, 1);
}
rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
@@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
- byte_cnt, o_buf);
+ byte_cnt, o_buf, 0);
break;
}
return rc;
@@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
{
u8 val;
+ int rc;
struct bnx2x *bp = params->bp;
u16 timeout;
/* Initialization time after hot-plug may take up to 300ms for
@@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
*/
for (timeout = 0; timeout < 60; timeout++) {
- if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
- == 0) {
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+ rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
+ params, 1,
+ 1, &val, 1);
+ else
+ rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
+ &val);
+ if (rc == 0) {
DP(NETIF_MSG_LINK,
"SFP+ module initialization took %d ms\n",
timeout * 5);
@@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
}
usleep_range(5000, 10000);
}
- return -EINVAL;
+ rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
+ return rc;
}
static void bnx2x_8727_power_module(struct bnx2x *bp,
@@ -9878,7 +9941,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
else
rc = bnx2x_8483x_disable_eee(phy, params, vars);
if (rc) {
- DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n");
+ DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n");
return rc;
}
} else {
@@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {
.format_fw_ver = (format_fw_ver_t)NULL,
.hw_reset = (hw_reset_t)NULL,
.set_link_led = (set_link_led_t)NULL,
- .phy_specific_func = (phy_specific_func_t)NULL
+ .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
};
static struct bnx2x_phy phy_warpcore = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
@@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
phy->media_type = ETH_PHY_BASE_T;
break;
case PORT_HW_CFG_NET_SERDES_IF_XFI:
+ phy->supported &= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_10000baseT_Full |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
phy->media_type = ETH_PHY_XFP_FIBER;
break;
case PORT_HW_CFG_NET_SERDES_IF_SFI:
@@ -12919,7 +12987,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
DP(NETIF_MSG_LINK, "Analyze TX Fault\n");
break;
default:
- DP(NETIF_MSG_LINK, "Analyze UNKOWN\n");
+ DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n");
}
DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
old_status, status);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index d5648fc666b..bd1fd3d87c2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
+ bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
- bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
if (IS_MF(bp))
low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
@@ -11902,7 +11903,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
/* disable FCOE L2 queue for E1x */
if (CHIP_IS_E1x(bp))
bp->flags |= NO_FCOE_FLAG;
-
+ /* disable FCOE for 57840 device, until FW supports it */
+ switch (ent->driver_data) {
+ case BCM57840_O:
+ case BCM57840_4_10:
+ case BCM57840_2_20:
+ case BCM57840_MFO:
+ case BCM57840_MF:
+ bp->flags |= NO_FCOE_FLAG;
+ }
#endif
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index c1cde11b0c6..0df1284df49 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3416,16 +3416,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
finicsum, cfcsum);
/*
- * If we're a pure NIC driver then disable all offloading facilities.
- * This will allow the firmware to optimize aspects of the hardware
- * configuration which will result in improved performance.
- */
- caps_cmd.ofldcaps = 0;
- caps_cmd.iscsicaps = 0;
- caps_cmd.rdmacaps = 0;
- caps_cmd.fcoecaps = 0;
-
- /*
* And now tell the firmware to use the configuration we just loaded.
*/
caps_cmd.op_to_write =
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 32eec15fe4c..730ae2cfa49 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -2519,6 +2519,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox)
{
struct fw_bye_cmd c;
+ memset(&c, 0, sizeof(c));
INIT_CMD(c, BYE, WRITE);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -2535,6 +2536,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox)
{
struct fw_initialize_cmd c;
+ memset(&c, 0, sizeof(c));
INIT_CMD(c, INITIALIZE, WRITE);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -2551,6 +2553,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
{
struct fw_reset_cmd c;
+ memset(&c, 0, sizeof(c));
INIT_CMD(c, RESET, WRITE);
c.val = htonl(reset);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
@@ -2828,7 +2831,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
HOSTPAGESIZEPF7(sge_hps));
t4_set_reg_field(adap, SGE_CONTROL,
- INGPADBOUNDARY(INGPADBOUNDARY_MASK) |
+ INGPADBOUNDARY_MASK |
EGRSTATUSPAGESIZE_MASK,
INGPADBOUNDARY(fl_align_log - 5) |
EGRSTATUSPAGESIZE(stat_len != 64));
@@ -3278,6 +3281,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
{
struct fw_vi_enable_cmd c;
+ memset(&c, 0, sizeof(c));
c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 1d03dcdd5e5..19ac096cb07 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1353,8 +1353,11 @@ static int gfar_restore(struct device *dev)
struct gfar_private *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->ndev;
- if (!netif_running(ndev))
+ if (!netif_running(ndev)) {
+ netif_device_attach(ndev);
+
return 0;
+ }
gfar_init_bds(ndev);
init_registers(ndev);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 56b20d17d0e..116f0e901be 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,
case ixgbe_mac_X540:
case ixgbe_mac_82599EB:
info->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index f8064df10cc..60ac46f4ac0 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev)
jme_clear_pm(jme);
JME_NAPI_ENABLE(jme);
- tasklet_enable(&jme->linkch_task);
- tasklet_enable(&jme->txclean_task);
- tasklet_hi_enable(&jme->rxclean_task);
- tasklet_hi_enable(&jme->rxempty_task);
+ tasklet_init(&jme->linkch_task, jme_link_change_tasklet,
+ (unsigned long) jme);
+ tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet,
+ (unsigned long) jme);
+ tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet,
+ (unsigned long) jme);
+ tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet,
+ (unsigned long) jme);
rc = jme_request_irq(jme);
if (rc)
@@ -1948,10 +1952,10 @@ jme_close(struct net_device *netdev)
JME_NAPI_DISABLE(jme);
- tasklet_disable(&jme->linkch_task);
- tasklet_disable(&jme->txclean_task);
- tasklet_disable(&jme->rxclean_task);
- tasklet_disable(&jme->rxempty_task);
+ tasklet_kill(&jme->linkch_task);
+ tasklet_kill(&jme->txclean_task);
+ tasklet_kill(&jme->rxclean_task);
+ tasklet_kill(&jme->rxempty_task);
jme_disable_rx_engine(jme);
jme_disable_tx_engine(jme);
@@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev,
tasklet_init(&jme->pcc_task,
jme_pcc_tasklet,
(unsigned long) jme);
- tasklet_init(&jme->linkch_task,
- jme_link_change_tasklet,
- (unsigned long) jme);
- tasklet_init(&jme->txclean_task,
- jme_tx_clean_tasklet,
- (unsigned long) jme);
- tasklet_init(&jme->rxclean_task,
- jme_rx_clean_tasklet,
- (unsigned long) jme);
- tasklet_init(&jme->rxempty_task,
- jme_rx_empty_tasklet,
- (unsigned long) jme);
- tasklet_disable_nosync(&jme->linkch_task);
- tasklet_disable_nosync(&jme->txclean_task);
- tasklet_disable_nosync(&jme->rxclean_task);
- tasklet_disable_nosync(&jme->rxempty_task);
jme->dpi.cur = PCC_P1;
jme->reg_ghc = 0;
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 9b9c2ac5c4c..d19a143aa5a 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -4026,7 +4026,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
dev0 = hw->dev[0];
unregister_netdev(dev0);
- tasklet_disable(&hw->phy_task);
+ tasklet_kill(&hw->phy_task);
spin_lock_irq(&hw->hw_lock);
hw->intr_mask = 0;
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 318fee91c79..69e01977a1d 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev)
/* Delay for receive task to stop scheduling itself. */
msleep(2000 / HZ);
- tasklet_disable(&hw_priv->rx_tasklet);
- tasklet_disable(&hw_priv->tx_tasklet);
+ tasklet_kill(&hw_priv->rx_tasklet);
+ tasklet_kill(&hw_priv->tx_tasklet);
free_irq(dev->irq, hw_priv->dev);
transmit_cleanup(hw_priv, 0);
@@ -5459,8 +5459,10 @@ static int prepare_hardware(struct net_device *dev)
rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev);
if (rc)
return rc;
- tasklet_enable(&hw_priv->rx_tasklet);
- tasklet_enable(&hw_priv->tx_tasklet);
+ tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
+ (unsigned long) hw_priv);
+ tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
+ (unsigned long) hw_priv);
hw->promiscuous = 0;
hw->all_multi = 0;
@@ -7033,16 +7035,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev,
spin_lock_init(&hw_priv->hwlock);
mutex_init(&hw_priv->lock);
- /* tasklet is enabled. */
- tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
- (unsigned long) hw_priv);
- tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
- (unsigned long) hw_priv);
-
- /* tasklet_enable will decrement the atomic counter. */
- tasklet_disable(&hw_priv->rx_tasklet);
- tasklet_disable(&hw_priv->tx_tasklet);
-
for (i = 0; i < TOTAL_PORT_NUM; i++)
init_waitqueue_head(&hw_priv->counter[i].counter);
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 53743f7a2ca..af8b4142088 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
pldat->dma_buff_base_p);
free_irq(ndev->irq, ndev);
iounmap(pldat->net_base);
+ mdiobus_unregister(pldat->mii_bus);
mdiobus_free(pldat->mii_bus);
clk_disable(pldat->clk);
clk_put(pldat->clk);
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index e7ff886e804..927aa33d434 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -3827,6 +3827,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
void __iomem *ioaddr = tp->mmio_addr;
switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_25:
+ case RTL_GIGA_MAC_VER_26:
case RTL_GIGA_MAC_VER_29:
case RTL_GIGA_MAC_VER_30:
case RTL_GIGA_MAC_VER_32:
@@ -4519,6 +4521,9 @@ static void rtl_set_rx_mode(struct net_device *dev)
mc_filter[1] = swab32(data);
}
+ if (tp->mac_version == RTL_GIGA_MAC_VER_35)
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+
RTL_W32(MAR0 + 4, mc_filter[1]);
RTL_W32(MAR0 + 0, mc_filter[0]);
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 62d1baf111e..c53c0f4e2ce 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -2110,7 +2110,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev)
static int __devinit smsc911x_init(struct net_device *dev)
{
struct smsc911x_data *pdata = netdev_priv(dev);
- unsigned int byte_test;
+ unsigned int byte_test, mask;
unsigned int to = 100;
SMSC_TRACE(pdata, probe, "Driver Parameters:");
@@ -2130,9 +2130,22 @@ static int __devinit smsc911x_init(struct net_device *dev)
/*
* poll the READY bit in PMT_CTRL. Any other access to the device is
* forbidden while this bit isn't set. Try for 100ms
+ *
+ * Note that this test is done before the WORD_SWAP register is
+ * programmed. So in some configurations the READY bit is at 16 before
+ * WORD_SWAP is written to. This issue is worked around by waiting
+ * until either bit 0 or bit 16 gets set in PMT_CTRL.
+ *
+ * SMSC has confirmed that checking bit 16 (marked as reserved in
+ * the datasheet) is fine since these bits "will either never be set
+ * or can only go high after READY does (so also indicate the device
+ * is ready)".
*/
- while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+
+ mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_);
+ while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to)
udelay(1000);
+
if (to == 0) {
pr_err("Device not READY in 100ms aborting\n");
return -ENODEV;
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 4e981001385..66e025ad5df 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev)
ingress_irq = rc;
tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU);
rc = request_irq(ingress_irq, tile_net_handle_ingress_irq,
- 0, NULL, NULL);
+ 0, "tile_net", NULL);
if (rc != 0) {
netdev_err(dev, "request_irq failed: %d\n", rc);
destroy_irq(ingress_irq);
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 0793299bd39..77e6db9dcfe 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -942,6 +942,10 @@ static int axienet_open(struct net_device *ndev)
phy_start(lp->phy_dev);
}
+ /* Enable tasklets for Axi DMA error handling */
+ tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
+ (unsigned long) lp);
+
/* Enable interrupts for Axi DMA Tx */
ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
if (ret)
@@ -950,8 +954,7 @@ static int axienet_open(struct net_device *ndev)
ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
if (ret)
goto err_rx_irq;
- /* Enable tasklets for Axi DMA error handling */
- tasklet_enable(&lp->dma_err_tasklet);
+
return 0;
err_rx_irq:
@@ -960,6 +963,7 @@ err_tx_irq:
if (lp->phy_dev)
phy_disconnect(lp->phy_dev);
lp->phy_dev = NULL;
+ tasklet_kill(&lp->dma_err_tasklet);
dev_err(lp->dev, "request_irq() failed\n");
return ret;
}
@@ -990,7 +994,7 @@ static int axienet_stop(struct net_device *ndev)
axienet_setoptions(ndev, lp->options &
~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
- tasklet_disable(&lp->dma_err_tasklet);
+ tasklet_kill(&lp->dma_err_tasklet);
free_irq(lp->tx_irq, ndev);
free_irq(lp->rx_irq, ndev);
@@ -1613,10 +1617,6 @@ static int __devinit axienet_of_probe(struct platform_device *op)
goto err_iounmap_2;
}
- tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
- (unsigned long) lp);
- tasklet_disable(&lp->dma_err_tasklet);
-
return 0;
err_iounmap_2:
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c
index c81e278629f..08d55b6bf27 100644
--- a/drivers/net/usb/cdc_eem.c
+++ b/drivers/net/usb/cdc_eem.c
@@ -31,6 +31,7 @@
#include <linux/usb/cdc.h>
#include <linux/usb/usbnet.h>
#include <linux/gfp.h>
+#include <linux/if_vlan.h>
/*
@@ -92,7 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
/* no jumbogram (16K) support for now */
- dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+ dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;
dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
return 0;
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 4cd582a4f62..74fab1a4015 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -540,10 +540,12 @@ advance:
(ctx->ether_desc == NULL) || (ctx->control != intf))
goto error;
- /* claim interfaces, if any */
- temp = usb_driver_claim_interface(driver, ctx->data, dev);
- if (temp)
- goto error;
+ /* claim data interface, if different from control */
+ if (ctx->data != ctx->control) {
+ temp = usb_driver_claim_interface(driver, ctx->data, dev);
+ if (temp)
+ goto error;
+ }
iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
@@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
tasklet_kill(&ctx->bh);
+ /* handle devices with combined control and data interface */
+ if (ctx->control == ctx->data)
+ ctx->data = NULL;
+
/* disconnect master --> disconnect slave */
if (intf == ctx->control && ctx->data) {
usb_set_intfdata(ctx->data, NULL);
@@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = {
.driver_info = (unsigned long) &wwan_info,
},
+ /* Huawei NCM devices disguised as vendor specific */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
+ .driver_info = (unsigned long)&wwan_info,
+ },
+ { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
+ .driver_info = (unsigned long)&wwan_info,
+ },
+
/* Generic CDC-NCM devices */
{ USB_INTERFACE_INFO(USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 7479a5761d0..362cb8cfeb9 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -184,7 +184,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
/* set the address, index & direction (read from PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
- addr = (phy_id << 11) | (idx << 6) | MII_READ_;
+ addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
check_warn_goto_done(ret, "Error writing MII_ADDR");
@@ -221,7 +221,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
/* set the address, index & direction (write to PHY) */
phy_id &= dev->mii.phy_id_mask;
idx &= dev->mii.reg_num_mask;
- addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
+ addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
check_warn_goto_done(ret, "Error writing MII_ADDR");
@@ -1344,6 +1344,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
} else {
u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
skb_push(skb, 4);
+ cpu_to_le32s(&csum_preamble);
memcpy(skb->data, &csum_preamble, 4);
}
}
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index cb04f900cc4..edb81ed0695 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -359,10 +359,12 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
void usbnet_defer_kevent (struct usbnet *dev, int work)
{
set_bit (work, &dev->flags);
- if (!schedule_work (&dev->kevent))
- netdev_err(dev->net, "kevent %d may have been dropped\n", work);
- else
+ if (!schedule_work (&dev->kevent)) {
+ if (net_ratelimit())
+ netdev_err(dev->net, "kevent %d may have been dropped\n", work);
+ } else {
netdev_dbg(dev->net, "kevent %d scheduled\n", work);
+ }
}
EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index ce9d4f2c977..0ae1bcc6da7 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+ u32 buf_size;
- tbi = tq->buf_info + tq->tx_ring.next2fill;
- tbi->map_type = VMXNET3_MAP_PAGE;
- tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
- 0, skb_frag_size(frag),
- DMA_TO_DEVICE);
+ buf_offset = 0;
+ len = skb_frag_size(frag);
+ while (len) {
+ tbi = tq->buf_info + tq->tx_ring.next2fill;
+ if (len < VMXNET3_MAX_TX_BUF_SIZE) {
+ buf_size = len;
+ dw2 |= len;
+ } else {
+ buf_size = VMXNET3_MAX_TX_BUF_SIZE;
+ /* spec says that for TxDesc.len, 0 == 2^14 */
+ }
+ tbi->map_type = VMXNET3_MAP_PAGE;
+ tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+ buf_offset, buf_size,
+ DMA_TO_DEVICE);
- tbi->len = skb_frag_size(frag);
+ tbi->len = buf_size;
- gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
- BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+ gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+ BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
- gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
- gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
- gdesc->dword[3] = 0;
+ gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
+ gdesc->dword[2] = cpu_to_le32(dw2);
+ gdesc->dword[3] = 0;
- dev_dbg(&adapter->netdev->dev,
- "txd[%u]: 0x%llu %u %u\n",
- tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
- le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
- vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
- dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+ dev_dbg(&adapter->netdev->dev,
+ "txd[%u]: 0x%llu %u %u\n",
+ tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
+ le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
+ vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+ dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+ len -= buf_size;
+ buf_offset += buf_size;
+ }
}
ctx->eop_txd = gdesc;
@@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
}
}
+static int txd_estimate(const struct sk_buff *skb)
+{
+ int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+ int i;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+ count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
+ }
+ return count;
+}
/*
* Transmits a pkt thru a given tq
@@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
union Vmxnet3_GenericDesc tempTxDesc;
#endif
- /* conservatively estimate # of descriptors to use */
- count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
- skb_shinfo(skb)->nr_frags + 1;
+ count = txd_estimate(skb);
ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 607976c0016..8b5c6191707 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1,5 +1,5 @@
/*
- * VXLAN: Virtual eXtensiable Local Area Network
+ * VXLAN: Virtual eXtensible Local Area Network
*
* Copyright (c) 2012 Vyatta Inc.
*
@@ -50,8 +50,8 @@
#define VXLAN_N_VID (1u << 24)
#define VXLAN_VID_MASK (VXLAN_N_VID - 1)
-/* VLAN + IP header + UDP + VXLAN */
-#define VXLAN_HEADROOM (4 + 20 + 8 + 8)
+/* IP header + UDP + VXLAN + Ethernet header */
+#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
#define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
@@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)
= container_of(p, struct vxlan_fdb, hlist);
unsigned long timeout;
- if (f->state == NUD_PERMANENT)
+ if (f->state & NUD_PERMANENT)
continue;
timeout = f->used + vxlan->age_interval * HZ;
@@ -1102,6 +1102,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
if (!tb[IFLA_MTU])
dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
+
+ /* update header length based on lower device */
+ dev->hard_header_len = lowerdev->hard_header_len +
+ VXLAN_HEADROOM;
}
if (data[IFLA_VXLAN_TOS])
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 378bd70256b..741918a2027 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
}
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+ bf->bf_next = NULL;
list_del(&bf->list);
spin_unlock_bh(&sc->tx.txbuflock);
@@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
- bool rc_update = true;
+ bool rc_update = true, isba;
struct ieee80211_tx_rate rates[4];
struct ath_frame_info *fi;
int nframes;
@@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
tid = ATH_AN_2_TID(an, tidno);
seq_first = tid->seq_start;
+ isba = ts->ts_flags & ATH9K_TX_BA;
/*
* The hardware occasionally sends a tx status for the wrong TID.
* In this case, the BA status cannot be considered valid and all
* subframes need to be retransmitted
+ *
+ * Only BlockAcks have a TID and therefore normal Acks cannot be
+ * checked
*/
- if (tidno != ts->tid)
+ if (isba && tidno != ts->tid)
txok = false;
isaggr = bf_isaggr(bf);
@@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
list_add_tail(&bf->list, &bf_head);
bf->bf_state.bf_type = 0;
+ bf->bf_next = NULL;
bf->bf_lastbf = bf;
ath_tx_fill_desc(sc, bf, txq, fi->framelen);
ath_tx_txqaddbuf(sc, txq, &bf_head, false);
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index 192251adf98..282eedec675 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue)
{
struct b43legacy_pio_txpacket *packet, *tmp_packet;
- tasklet_disable(&queue->txtask);
+ tasklet_kill(&queue->txtask);
list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
free_txpacket(packet, 0);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index a6f1e816600..481345c23de 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -4401,7 +4401,7 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
{
-#ifndef CONFIG_BRCMFISCAN
+#ifndef CONFIG_BRCMISCAN
/* scheduled scan settings */
wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index ff8162d4c45..fa4d1b8cd9f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -521,7 +521,7 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw,
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
if (iwlagn_tx_skb(priv, control->sta, skb))
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(hw, skb);
}
static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 7ff3f143067..408132cf83c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -2114,7 +2114,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);
iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
- dev_kfree_skb_any(skb);
+ ieee80211_free_txskb(priv->hw, skb);
}
static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 17c8e5d8268..bb69f8f90b3 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -321,6 +321,14 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
dma_map_page(trans->dev, page, 0,
PAGE_SIZE << trans_pcie->rx_page_order,
DMA_FROM_DEVICE);
+ if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+ rxb->page = NULL;
+ spin_lock_irqsave(&rxq->lock, flags);
+ list_add(&rxb->list, &rxq->rx_used);
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ __free_pages(page, trans_pcie->rx_page_order);
+ return;
+ }
/* dma address must be no more than 36 bits */
BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
/* and also 256 byte aligned! */
@@ -488,8 +496,19 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
dma_map_page(trans->dev, rxb->page, 0,
PAGE_SIZE << trans_pcie->rx_page_order,
DMA_FROM_DEVICE);
- list_add_tail(&rxb->list, &rxq->rx_free);
- rxq->free_count++;
+ if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+ /*
+ * free the page(s) as well to not break
+ * the invariant that the items on the used
+ * list have no page(s)
+ */
+ __free_pages(rxb->page, trans_pcie->rx_page_order);
+ rxb->page = NULL;
+ list_add_tail(&rxb->list, &rxq->rx_used);
+ } else {
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+ }
} else
list_add_tail(&rxb->list, &rxq->rx_used);
spin_unlock_irqrestore(&rxq->lock, flags);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 01dc8891070..59474ae0aec 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
/*
* Check if temperature compensation is supported.
*/
- if (tssi_bounds[4] == 0xff)
+ if (tssi_bounds[4] == 0xff || step == 0xff)
return 0;
/*
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 6241fd05bd4..a543746fb35 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -320,10 +320,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
} else
next = dev->bus_list.next;
- /* Run device routines with the device locked */
- device_lock(&dev->dev);
retval = cb(dev, userdata);
- device_unlock(&dev->dev);
if (retval)
break;
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 94c6e2aa03d..6c94fc9489e 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -398,6 +398,8 @@ static void pci_device_shutdown(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *drv = pci_dev->driver;
+ pm_runtime_resume(dev);
+
if (drv && drv->shutdown)
drv->shutdown(pci_dev);
pci_msi_shutdown(pci_dev);
@@ -408,16 +410,6 @@ static void pci_device_shutdown(struct device *dev)
* continue to do DMA
*/
pci_disable_device(pci_dev);
-
- /*
- * Devices may be enabled to wake up by runtime PM, but they need not
- * be supposed to wake up the system from its "power off" state (e.g.
- * ACPI S5). Therefore disable wakeup for all devices that aren't
- * supposed to wake up the system at this point. The state argument
- * will be ignored by pci_enable_wake().
- */
- if (!device_may_wakeup(dev))
- pci_enable_wake(pci_dev, PCI_UNKNOWN, false);
}
#ifdef CONFIG_PM
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 02d107b1528..f39378d9da1 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
}
struct device_attribute vga_attr = __ATTR_RO(boot_vga);
-static void
-pci_config_pm_runtime_get(struct pci_dev *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device *parent = dev->parent;
-
- if (parent)
- pm_runtime_get_sync(parent);
- pm_runtime_get_noresume(dev);
- /*
- * pdev->current_state is set to PCI_D3cold during suspending,
- * so wait until suspending completes
- */
- pm_runtime_barrier(dev);
- /*
- * Only need to resume devices in D3cold, because config
- * registers are still accessible for devices suspended but
- * not in D3cold.
- */
- if (pdev->current_state == PCI_D3cold)
- pm_runtime_resume(dev);
-}
-
-static void
-pci_config_pm_runtime_put(struct pci_dev *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device *parent = dev->parent;
-
- pm_runtime_put(dev);
- if (parent)
- pm_runtime_put_sync(parent);
-}
-
static ssize_t
pci_read_config(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 54858838f09..aabf64798bd 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(pci_dev_run_wake);
+void pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+
+ if (parent)
+ pm_runtime_get_sync(parent);
+ pm_runtime_get_noresume(dev);
+ /*
+ * pdev->current_state is set to PCI_D3cold during suspending,
+ * so wait until suspending completes
+ */
+ pm_runtime_barrier(dev);
+ /*
+ * Only need to resume devices in D3cold, because config
+ * registers are still accessible for devices suspended but
+ * not in D3cold.
+ */
+ if (pdev->current_state == PCI_D3cold)
+ pm_runtime_resume(dev);
+}
+
+void pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+
+ pm_runtime_put(dev);
+ if (parent)
+ pm_runtime_put_sync(parent);
+}
+
/**
* pci_pm_init - Initialize PM functions of given PCI device
* @dev: PCI device to handle.
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index bacbcba69cf..fd92aab9904 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev);
extern int pci_finish_runtime_suspend(struct pci_dev *dev);
extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
extern void pci_wakeup_bus(struct pci_bus *bus);
+extern void pci_config_pm_runtime_get(struct pci_dev *dev);
+extern void pci_config_pm_runtime_put(struct pci_dev *dev);
extern void pci_pm_init(struct pci_dev *dev);
extern void platform_pci_wakeup_init(struct pci_dev *dev);
extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 06bad96af41..af4e31cd3a3 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
struct aer_broadcast_data *result_data;
result_data = (struct aer_broadcast_data *) data;
+ device_lock(&dev->dev);
dev->error_state = result_data->state;
if (!dev->driver ||
@@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data)
dev->driver ?
"no AER-aware driver" : "no driver");
}
- return 0;
+ goto out;
}
err_handler = dev->driver->err_handler;
vote = err_handler->error_detected(dev, result_data->state);
result_data->result = merge_result(result_data->result, vote);
+out:
+ device_unlock(&dev->dev);
return 0;
}
@@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data)
struct aer_broadcast_data *result_data;
result_data = (struct aer_broadcast_data *) data;
+ device_lock(&dev->dev);
if (!dev->driver ||
!dev->driver->err_handler ||
!dev->driver->err_handler->mmio_enabled)
- return 0;
+ goto out;
err_handler = dev->driver->err_handler;
vote = err_handler->mmio_enabled(dev);
result_data->result = merge_result(result_data->result, vote);
+out:
+ device_unlock(&dev->dev);
return 0;
}
@@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data)
struct aer_broadcast_data *result_data;
result_data = (struct aer_broadcast_data *) data;
+ device_lock(&dev->dev);
if (!dev->driver ||
!dev->driver->err_handler ||
!dev->driver->err_handler->slot_reset)
- return 0;
+ goto out;
err_handler = dev->driver->err_handler;
vote = err_handler->slot_reset(dev);
result_data->result = merge_result(result_data->result, vote);
+out:
+ device_unlock(&dev->dev);
return 0;
}
@@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data)
{
const struct pci_error_handlers *err_handler;
+ device_lock(&dev->dev);
dev->error_state = pci_channel_io_normal;
if (!dev->driver ||
!dev->driver->err_handler ||
!dev->driver->err_handler->resume)
- return 0;
+ goto out;
err_handler = dev->driver->err_handler;
err_handler->resume(dev);
+out:
+ device_unlock(&dev->dev);
return 0;
}
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index d03a7a39b2d..ed129b41462 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -272,7 +272,8 @@ static int get_port_device_capability(struct pci_dev *dev)
}
/* Hot-Plug Capable */
- if (cap_mask & PCIE_PORT_SERVICE_HP) {
+ if ((cap_mask & PCIE_PORT_SERVICE_HP) &&
+ dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {
pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
if (reg32 & PCI_EXP_SLTCAP_HPC) {
services |= PCIE_PORT_SERVICE_HP;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index eb907a8faf2..9b8505ccc56 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if (!access_ok(VERIFY_WRITE, buf, cnt))
return -EINVAL;
+ pci_config_pm_runtime_get(dev);
+
if ((pos & 1) && cnt) {
unsigned char val;
pci_user_read_config_byte(dev, pos, &val);
@@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
cnt--;
}
+ pci_config_pm_runtime_put(dev);
+
*ppos = pos;
return nbytes;
}
@@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
if (!access_ok(VERIFY_READ, buf, cnt))
return -EINVAL;
+ pci_config_pm_runtime_get(dev);
+
if ((pos & 1) && cnt) {
unsigned char val;
__get_user(val, buf);
@@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
cnt--;
}
+ pci_config_pm_runtime_put(dev);
+
*ppos = pos;
i_size_write(ino, dp->size);
return nbytes;
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index fa74efe8220..25c4b1993b3 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -25,7 +25,7 @@
#include <asm/sizes.h>
#include <mach/mux.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
/* NOTE: don't expect this to support many I/O cards. The 16xx chips have
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 7bf914df6e9..011133772d2 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -179,34 +179,16 @@ config PINCTRL_COH901
config PINCTRL_SAMSUNG
bool "Samsung pinctrl driver"
+ depends on OF && GPIOLIB
select PINMUX
select PINCONF
config PINCTRL_EXYNOS4
bool "Pinctrl driver data for Exynos4 SoC"
+ depends on OF && GPIOLIB
select PINCTRL_SAMSUNG
-config PINCTRL_MVEBU
- bool
- depends on ARCH_MVEBU
- select PINMUX
- select PINCONF
-
-config PINCTRL_DOVE
- bool
- select PINCTRL_MVEBU
-
-config PINCTRL_KIRKWOOD
- bool
- select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_370
- bool
- select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_XP
- bool
- select PINCTRL_MVEBU
+source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/spear/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f395ba5cec2..3cb6a0a668a 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -36,12 +36,8 @@ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o
-obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
-obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
-obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
-obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
-obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
+obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 2e39c04fc16..cec6072cd7c 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -563,6 +563,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
return -EPROBE_DEFER;
}
+ setting->dev_name = map->dev_name;
+
switch (map->type) {
case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_map_to_setting(map, setting);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 1f40ff68a8c..12f5694f3d5 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -105,12 +105,14 @@ struct pinctrl_setting_configs {
* @type: the type of setting
* @pctldev: pin control device handling to be programmed. Not used for
* PIN_MAP_TYPE_DUMMY_STATE.
+ * @dev_name: the name of the device using this state
* @data: Data specific to the setting type
*/
struct pinctrl_setting {
struct list_head node;
enum pinctrl_map_type type;
struct pinctrl_dev *pctldev;
+ const char *dev_name;
union {
struct pinctrl_setting_mux mux;
struct pinctrl_setting_configs configs;
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
new file mode 100644
index 00000000000..366fa541ee9
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -0,0 +1,24 @@
+if PLAT_ORION
+
+config PINCTRL_MVEBU
+ bool
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_DOVE
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_KIRKWOOD
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_370
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_XP
+ bool
+ select PINCTRL_MVEBU
+
+endif
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
new file mode 100644
index 00000000000..37c253297af
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
+obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
+obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
+obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
+obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
index c907647de6a..c907647de6a 100644
--- a/drivers/pinctrl/pinctrl-armada-370.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index 40bd52a46b4..40bd52a46b4 100644
--- a/drivers/pinctrl/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index ffe74b27d66..40c9c3eecd9 100644
--- a/drivers/pinctrl/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -22,22 +22,22 @@
#include "pinctrl-mvebu.h"
-#define DOVE_SB_REGS_VIRT_BASE 0xfde00000
-#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0200)
+#define DOVE_SB_REGS_VIRT_BASE IOMEM(0xfde00000)
+#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0200)
#define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
#define DOVE_AU0_AC97_SEL BIT(16)
-#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE | 0xe802C)
+#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C)
#define DOVE_TWSI_ENABLE_OPTION1 BIT(7)
-#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE | 0xe8030)
+#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE + 0xe8030)
#define DOVE_TWSI_ENABLE_OPTION2 BIT(20)
#define DOVE_TWSI_ENABLE_OPTION3 BIT(21)
#define DOVE_TWSI_OPTION3_GPIO BIT(22)
-#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE | 0xe8034)
+#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE + 0xe8034)
#define DOVE_SSP_ON_AU1 BIT(0)
-#define DOVE_MPP_GENERAL_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xe803c)
+#define DOVE_MPP_GENERAL_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xe803c)
#define DOVE_AU1_SPDIFO_GPIO_EN BIT(1)
#define DOVE_NAND_GPIO_EN BIT(0)
-#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0400)
#define DOVE_MPP_CTRL4_VIRT_BASE (DOVE_GPIO_LO_VIRT_BASE + 0x40)
#define DOVE_SPI_GPIO_SEL BIT(5)
#define DOVE_UART1_GPIO_SEL BIT(4)
@@ -234,6 +234,14 @@ static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+ /*
+ * clear all audio1 related bits before configure
+ */
+ gcfg2 &= ~DOVE_TWSI_OPTION3_GPIO;
+ gmpp &= ~DOVE_AU1_SPDIFO_GPIO_EN;
+ sspc1 &= ~DOVE_SSP_ON_AU1;
+ mpp4 &= ~DOVE_AU1_GPIO_SEL;
+
if (config & BIT(0))
gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
if (config & BIT(1))
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
new file mode 100644
index 00000000000..fa6ce31c94d
--- /dev/null
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -0,0 +1,484 @@
+/*
+ * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define V(f6180, f6190, f6192, f6281, f6282, dx4122) \
+ ((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
+ (f6281 << 3) | (f6282 << 4) | (dx4122 << 5))
+
+enum kirkwood_variant {
+ VARIANT_MV88F6180 = V(1, 0, 0, 0, 0, 0),
+ VARIANT_MV88F6190 = V(0, 1, 0, 0, 0, 0),
+ VARIANT_MV88F6192 = V(0, 0, 1, 0, 0, 0),
+ VARIANT_MV88F6281 = V(0, 0, 0, 1, 0, 0),
+ VARIANT_MV88F6282 = V(0, 0, 0, 0, 1, 0),
+ VARIANT_MV98DX4122 = V(0, 0, 0, 0, 0, 1),
+};
+
+static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
+ MPP_MODE(0,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1))),
+ MPP_MODE(1,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1))),
+ MPP_MODE(2,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1))),
+ MPP_MODE(3,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1))),
+ MPP_MODE(4,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0))),
+ MPP_MODE(5,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(6,
+ MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0, 0))),
+ MPP_MODE(7,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(8,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0))),
+ MPP_MODE(9,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0))),
+ MPP_MODE(10,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0, 0))),
+ MPP_MODE(11,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0))),
+ MPP_MODE(12,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(13,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(14,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1, 0))),
+ MPP_MODE(15,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(16,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1, 0))),
+ MPP_MODE(17,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(18,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(19,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1, 1))),
+ MPP_MODE(20,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 0, 0, 0, 0, 0))),
+ MPP_MODE(21,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(22,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(23,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(24,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(25,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(26,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(27,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(28,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(29,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(30,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(31,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(32,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(33,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(34,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(35,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 1, 1, 1, 1, 0))),
+ MPP_MODE(36,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(37,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(38,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(39,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(40,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(41,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(42,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(43,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(44,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(45,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(46,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(47,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(48,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1, 0))),
+ MPP_MODE(49,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0, 0)),
+ MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1, 0))),
+};
+
+static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
+ MPP_REG_CTRL(0, 29),
+};
+
+static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 30),
+};
+
+static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
+ MPP_REG_CTRL(0, 35),
+};
+
+static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 4),
+};
+
+static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
+ MPP_REG_CTRL(0, 49),
+};
+
+static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 18),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6180_info = {
+ .variant = VARIANT_MV88F6180,
+ .controls = mv88f6180_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f6180_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6190_info = {
+ .variant = VARIANT_MV88F6190,
+ .controls = mv88f619x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f619x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6192_info = {
+ .variant = VARIANT_MV88F6192,
+ .controls = mv88f619x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f619x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6281_info = {
+ .variant = VARIANT_MV88F6281,
+ .controls = mv88f628x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f628x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6282_info = {
+ .variant = VARIANT_MV88F6282,
+ .controls = mv88f628x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f628x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv98dx4122_info = {
+ .variant = VARIANT_MV98DX4122,
+ .controls = mv88f628x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f628x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
+ { .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
+ { .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
+ { .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
+ { .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
+ { .compatible = "marvell,98dx4122-pinctrl", .data = &mv98dx4122_info },
+ { }
+};
+
+static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match =
+ of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
+ pdev->dev.platform_data = match->data;
+ return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
+{
+ return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver kirkwood_pinctrl_driver = {
+ .driver = {
+ .name = "kirkwood-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
+ },
+ .probe = kirkwood_pinctrl_probe,
+ .remove = __devexit_p(kirkwood_pinctrl_remove),
+};
+
+module_platform_driver(kirkwood_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 8e6266c6249..6c44b7e8964 100644
--- a/drivers/pinctrl/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -24,7 +24,6 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
-#include "core.h"
#include "pinctrl-mvebu.h"
#define MPPS_PER_REG 8
diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index 90bd3beee86..90bd3beee86 100644
--- a/drivers/pinctrl/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 21362f48d37..19fab68a9fb 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -40,46 +40,46 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
static void exynos_gpio_irq_unmask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask &= ~(1 << edata->pin);
+ mask &= ~(1 << irqd->hwirq);
writel(mask, d->virt_base + reg_mask);
}
static void exynos_gpio_irq_mask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask |= 1 << edata->pin;
+ mask |= 1 << irqd->hwirq;
writel(mask, d->virt_base + reg_mask);
}
static void exynos_gpio_irq_ack(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset;
- writel(1 << edata->pin, d->virt_base + reg_pend);
+ writel(1 << irqd->hwirq, d->virt_base + reg_pend);
}
static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
{
- struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
struct samsung_pin_ctrl *ctrl = d->ctrl;
- struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
- struct samsung_pin_bank *bank = edata->bank;
- unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
+ unsigned int pin = irqd->hwirq;
+ unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
unsigned int con, trig_type;
- unsigned long reg_con = ctrl->geint_con + edata->eint_offset;
+ unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
unsigned int mask;
switch (type) {
@@ -114,7 +114,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
writel(con, d->virt_base + reg_con);
reg_con = bank->pctl_offset;
- shift = edata->pin * bank->func_width;
+ shift = pin * bank->func_width;
mask = (1 << bank->func_width) - 1;
con = readl(d->virt_base + reg_con);
@@ -136,82 +136,23 @@ static struct irq_chip exynos_gpio_irq_chip = {
.irq_set_type = exynos_gpio_irq_set_type,
};
-/*
- * given a controller-local external gpio interrupt number, prepare the handler
- * data for it.
- */
-static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
- struct samsung_pinctrl_drv_data *d)
-{
- struct samsung_pin_bank *bank = d->ctrl->pin_banks;
- struct exynos_geint_data *eint_data;
- unsigned int nr_banks = d->ctrl->nr_banks, idx;
- unsigned int irq_base = 0, eint_offset = 0;
-
- if (hw >= d->ctrl->nr_gint) {
- dev_err(d->dev, "unsupported ext-gpio interrupt\n");
- return NULL;
- }
-
- for (idx = 0; idx < nr_banks; idx++, bank++) {
- if (bank->eint_type != EINT_TYPE_GPIO)
- continue;
- if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
- break;
- irq_base += bank->nr_pins;
- eint_offset += 4;
- }
-
- if (idx == nr_banks) {
- dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
- return NULL;
- }
-
- eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
- if (!eint_data) {
- dev_err(d->dev, "no memory for eint-gpio data\n");
- return NULL;
- }
-
- eint_data->bank = bank;
- eint_data->pin = hw - irq_base;
- eint_data->eint_offset = eint_offset;
- return eint_data;
-}
-
static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
- struct samsung_pinctrl_drv_data *d = h->host_data;
- struct exynos_geint_data *eint_data;
-
- eint_data = exynos_get_eint_data(hw, d);
- if (!eint_data)
- return -EINVAL;
+ struct samsung_pin_bank *b = h->host_data;
- irq_set_handler_data(virq, eint_data);
- irq_set_chip_data(virq, h->host_data);
+ irq_set_chip_data(virq, b);
irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
handle_level_irq);
set_irq_flags(virq, IRQF_VALID);
return 0;
}
-static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
-{
- struct samsung_pinctrl_drv_data *d = h->host_data;
- struct exynos_geint_data *eint_data;
-
- eint_data = irq_get_handler_data(virq);
- devm_kfree(d->dev, eint_data);
-}
-
/*
* irq domain callbacks for external gpio interrupt controller.
*/
static const struct irq_domain_ops exynos_gpio_irqd_ops = {
.map = exynos_gpio_irq_map,
- .unmap = exynos_gpio_irq_unmap,
.xlate = irq_domain_xlate_twocell,
};
@@ -230,7 +171,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
return IRQ_HANDLED;
bank += (group - 1);
- virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
+ virq = irq_linear_revmap(bank->irq_domain, pin);
if (!virq)
return IRQ_NONE;
generic_handle_irq(virq);
@@ -243,8 +184,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
*/
static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
{
+ struct samsung_pin_bank *bank;
struct device *dev = d->dev;
unsigned int ret;
+ unsigned int i;
if (!d->irq) {
dev_err(dev, "irq number not available\n");
@@ -258,11 +201,16 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
return -ENXIO;
}
- d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
- &exynos_gpio_irqd_ops, d);
- if (!d->gpio_irqd) {
- dev_err(dev, "gpio irq domain allocation failed\n");
- return -ENXIO;
+ bank = d->ctrl->pin_banks;
+ for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+ if (bank->eint_type != EINT_TYPE_GPIO)
+ continue;
+ bank->irq_domain = irq_domain_add_linear(bank->of_node,
+ bank->nr_pins, &exynos_gpio_irqd_ops, bank);
+ if (!bank->irq_domain) {
+ dev_err(dev, "gpio irq domain add failed\n");
+ return -ENXIO;
+ }
}
return 0;
@@ -270,48 +218,46 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
static void exynos_wkup_irq_unmask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+ struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = b->drvdata;
+ unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask &= ~(1 << pin);
+ mask &= ~(1 << irqd->hwirq);
writel(mask, d->virt_base + reg_mask);
}
static void exynos_wkup_irq_mask(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+ struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = b->drvdata;
+ unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
unsigned long mask;
mask = readl(d->virt_base + reg_mask);
- mask |= 1 << pin;
+ mask |= 1 << irqd->hwirq;
writel(mask, d->virt_base + reg_mask);
}
static void exynos_wkup_irq_ack(struct irq_data *irqd)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long pend = d->ctrl->weint_pend + (bank << 2);
+ struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = b->drvdata;
+ unsigned long pend = d->ctrl->weint_pend + b->eint_offset;
- writel(1 << pin, d->virt_base + pend);
+ writel(1 << irqd->hwirq, d->virt_base + pend);
}
static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
{
- struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
- unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
- unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
- unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned int pin = irqd->hwirq;
+ unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
unsigned long con, trig_type;
+ unsigned int mask;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
@@ -343,6 +289,16 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
con &= ~(EXYNOS_EINT_CON_MASK << shift);
con |= trig_type << shift;
writel(con, d->virt_base + reg_con);
+
+ reg_con = bank->pctl_offset;
+ shift = pin * bank->func_width;
+ mask = (1 << bank->func_width) - 1;
+
+ con = readl(d->virt_base + reg_con);
+ con &= ~(mask << shift);
+ con |= EXYNOS_EINT_FUNC << shift;
+ writel(con, d->virt_base + reg_con);
+
return 0;
}
@@ -361,6 +317,7 @@ static struct irq_chip exynos_wkup_irq_chip = {
static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
{
struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+ struct samsung_pin_bank *bank = eintd->bank;
struct irq_chip *chip = irq_get_chip(irq);
int eint_irq;
@@ -370,20 +327,20 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
if (chip->irq_ack)
chip->irq_ack(&desc->irq_data);
- eint_irq = irq_linear_revmap(eintd->domain, eintd->irq);
+ eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq);
generic_handle_irq(eint_irq);
chip->irq_unmask(&desc->irq_data);
chained_irq_exit(chip, desc);
}
-static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
- struct irq_domain *domain)
+static inline void exynos_irq_demux_eint(unsigned long pend,
+ struct irq_domain *domain)
{
unsigned int irq;
while (pend) {
irq = fls(pend) - 1;
- generic_handle_irq(irq_find_mapping(domain, irq_base + irq));
+ generic_handle_irq(irq_find_mapping(domain, irq));
pend &= ~(1 << irq);
}
}
@@ -392,18 +349,22 @@ static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_get_chip(irq);
- struct exynos_weint_data *eintd = irq_get_handler_data(irq);
- struct samsung_pinctrl_drv_data *d = eintd->domain->host_data;
+ struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
+ struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
+ struct samsung_pin_ctrl *ctrl = d->ctrl;
unsigned long pend;
unsigned long mask;
+ int i;
chained_irq_enter(chip, desc);
- pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8);
- mask = readl(d->virt_base + d->ctrl->weint_mask + 0x8);
- exynos_irq_demux_eint(16, pend & ~mask, eintd->domain);
- pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC);
- mask = readl(d->virt_base + d->ctrl->weint_mask + 0xC);
- exynos_irq_demux_eint(24, pend & ~mask, eintd->domain);
+
+ for (i = 0; i < eintd->nr_banks; ++i) {
+ struct samsung_pin_bank *b = eintd->banks[i];
+ pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset);
+ mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset);
+ exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
+ }
+
chained_irq_exit(chip, desc);
}
@@ -433,7 +394,11 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
struct device *dev = d->dev;
struct device_node *wkup_np = NULL;
struct device_node *np;
+ struct samsung_pin_bank *bank;
struct exynos_weint_data *weint_data;
+ struct exynos_muxed_weint_data *muxed_data;
+ unsigned int muxed_banks = 0;
+ unsigned int i;
int idx, irq;
for_each_child_of_node(dev->of_node, np) {
@@ -445,90 +410,124 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
if (!wkup_np)
return -ENODEV;
- d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint,
- &exynos_wkup_irqd_ops, d);
- if (!d->wkup_irqd) {
- dev_err(dev, "wakeup irq domain allocation failed\n");
- return -ENXIO;
- }
+ bank = d->ctrl->pin_banks;
+ for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+ if (bank->eint_type != EINT_TYPE_WKUP)
+ continue;
- weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL);
- if (!weint_data) {
- dev_err(dev, "could not allocate memory for weint_data\n");
- return -ENOMEM;
- }
+ bank->irq_domain = irq_domain_add_linear(bank->of_node,
+ bank->nr_pins, &exynos_wkup_irqd_ops, bank);
+ if (!bank->irq_domain) {
+ dev_err(dev, "wkup irq domain add failed\n");
+ return -ENXIO;
+ }
- irq = irq_of_parse_and_map(wkup_np, 16);
- if (irq) {
- weint_data[16].domain = d->wkup_irqd;
- irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
- irq_set_handler_data(irq, &weint_data[16]);
- } else {
- dev_err(dev, "irq number for EINT16-32 not found\n");
- }
+ if (!of_find_property(bank->of_node, "interrupts", NULL)) {
+ bank->eint_type = EINT_TYPE_WKUP_MUX;
+ ++muxed_banks;
+ continue;
+ }
- for (idx = 0; idx < 16; idx++) {
- weint_data[idx].domain = d->wkup_irqd;
- weint_data[idx].irq = idx;
+ weint_data = devm_kzalloc(dev, bank->nr_pins
+ * sizeof(*weint_data), GFP_KERNEL);
+ if (!weint_data) {
+ dev_err(dev, "could not allocate memory for weint_data\n");
+ return -ENOMEM;
+ }
- irq = irq_of_parse_and_map(wkup_np, idx);
- if (irq) {
+ for (idx = 0; idx < bank->nr_pins; ++idx) {
+ irq = irq_of_parse_and_map(bank->of_node, idx);
+ if (!irq) {
+ dev_err(dev, "irq number for eint-%s-%d not found\n",
+ bank->name, idx);
+ continue;
+ }
+ weint_data[idx].irq = idx;
+ weint_data[idx].bank = bank;
irq_set_handler_data(irq, &weint_data[idx]);
irq_set_chained_handler(irq, exynos_irq_eint0_15);
- } else {
- dev_err(dev, "irq number for eint-%x not found\n", idx);
}
}
+
+ if (!muxed_banks)
+ return 0;
+
+ irq = irq_of_parse_and_map(wkup_np, 0);
+ if (!irq) {
+ dev_err(dev, "irq number for muxed EINTs not found\n");
+ return 0;
+ }
+
+ muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
+ + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
+ if (!muxed_data) {
+ dev_err(dev, "could not allocate memory for muxed_data\n");
+ return -ENOMEM;
+ }
+
+ irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
+ irq_set_handler_data(irq, muxed_data);
+
+ bank = d->ctrl->pin_banks;
+ idx = 0;
+ for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+ if (bank->eint_type != EINT_TYPE_WKUP_MUX)
+ continue;
+
+ muxed_data->banks[idx++] = bank;
+ }
+ muxed_data->nr_banks = muxed_banks;
+
return 0;
}
/* pin banks of exynos4210 pin-controller 0 */
static struct samsung_pin_bank exynos4210_pin_banks0[] = {
- EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_A0, "gpa0"),
- EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_A1, "gpa1"),
- EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_B, "gpb"),
- EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_C0, "gpc0"),
- EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_C1, "gpc1"),
- EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_D0, "gpd0"),
- EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_D1, "gpd1"),
- EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_E0, "gpe0"),
- EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_E1, "gpe1"),
- EXYNOS_PIN_BANK_EINTG(0x120, EXYNOS4210_GPIO_E2, "gpe2"),
- EXYNOS_PIN_BANK_EINTG(0x140, EXYNOS4210_GPIO_E3, "gpe3"),
- EXYNOS_PIN_BANK_EINTG(0x160, EXYNOS4210_GPIO_E4, "gpe4"),
- EXYNOS_PIN_BANK_EINTG(0x180, EXYNOS4210_GPIO_F0, "gpf0"),
- EXYNOS_PIN_BANK_EINTG(0x1A0, EXYNOS4210_GPIO_F1, "gpf1"),
- EXYNOS_PIN_BANK_EINTG(0x1C0, EXYNOS4210_GPIO_F2, "gpf2"),
- EXYNOS_PIN_BANK_EINTG(0x1E0, EXYNOS4210_GPIO_F3, "gpf3"),
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+ EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+ EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+ EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+ EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20),
+ EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24),
+ EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28),
+ EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+ EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+ EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+ EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
};
/* pin banks of exynos4210 pin-controller 1 */
static struct samsung_pin_bank exynos4210_pin_banks1[] = {
- EXYNOS_PIN_BANK_EINTG(0x000, EXYNOS4210_GPIO_J0, "gpj0"),
- EXYNOS_PIN_BANK_EINTG(0x020, EXYNOS4210_GPIO_J1, "gpj1"),
- EXYNOS_PIN_BANK_EINTG(0x040, EXYNOS4210_GPIO_K0, "gpk0"),
- EXYNOS_PIN_BANK_EINTG(0x060, EXYNOS4210_GPIO_K1, "gpk1"),
- EXYNOS_PIN_BANK_EINTG(0x080, EXYNOS4210_GPIO_K2, "gpk2"),
- EXYNOS_PIN_BANK_EINTG(0x0A0, EXYNOS4210_GPIO_K3, "gpk3"),
- EXYNOS_PIN_BANK_EINTG(0x0C0, EXYNOS4210_GPIO_L0, "gpl0"),
- EXYNOS_PIN_BANK_EINTG(0x0E0, EXYNOS4210_GPIO_L1, "gpl1"),
- EXYNOS_PIN_BANK_EINTG(0x100, EXYNOS4210_GPIO_L2, "gpl2"),
- EXYNOS_PIN_BANK_EINTN(0x120, EXYNOS4210_GPIO_Y0, "gpy0"),
- EXYNOS_PIN_BANK_EINTN(0x140, EXYNOS4210_GPIO_Y1, "gpy1"),
- EXYNOS_PIN_BANK_EINTN(0x160, EXYNOS4210_GPIO_Y2, "gpy2"),
- EXYNOS_PIN_BANK_EINTN(0x180, EXYNOS4210_GPIO_Y3, "gpy3"),
- EXYNOS_PIN_BANK_EINTN(0x1A0, EXYNOS4210_GPIO_Y4, "gpy4"),
- EXYNOS_PIN_BANK_EINTN(0x1C0, EXYNOS4210_GPIO_Y5, "gpy5"),
- EXYNOS_PIN_BANK_EINTN(0x1E0, EXYNOS4210_GPIO_Y6, "gpy6"),
- EXYNOS_PIN_BANK_EINTN(0xC00, EXYNOS4210_GPIO_X0, "gpx0"),
- EXYNOS_PIN_BANK_EINTN(0xC20, EXYNOS4210_GPIO_X1, "gpx1"),
- EXYNOS_PIN_BANK_EINTN(0xC40, EXYNOS4210_GPIO_X2, "gpx2"),
- EXYNOS_PIN_BANK_EINTN(0xC60, EXYNOS4210_GPIO_X3, "gpx3"),
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+ EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+ EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18),
+ EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
+ EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
+ EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
+ EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
};
/* pin banks of exynos4210 pin-controller 2 */
static struct samsung_pin_bank exynos4210_pin_banks2[] = {
- EXYNOS_PIN_BANK_EINTN(0x000, EXYNOS4210_GPIO_Z, "gpz"),
+ EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
};
/*
@@ -540,9 +539,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = exynos4210_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos4210_pin_banks0),
- .base = EXYNOS4210_GPIO_A0_START,
- .nr_pins = EXYNOS4210_GPIOA_NR_PINS,
- .nr_gint = EXYNOS4210_GPIOA_NR_GINT,
.geint_con = EXYNOS_GPIO_ECON_OFFSET,
.geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
.geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
@@ -553,10 +549,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
/* pin-controller instance 1 data */
.pin_banks = exynos4210_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos4210_pin_banks1),
- .base = EXYNOS4210_GPIOA_NR_PINS,
- .nr_pins = EXYNOS4210_GPIOB_NR_PINS,
- .nr_gint = EXYNOS4210_GPIOB_NR_GINT,
- .nr_wint = 32,
.geint_con = EXYNOS_GPIO_ECON_OFFSET,
.geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
.geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
@@ -571,9 +563,116 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
/* pin-controller instance 2 data */
.pin_banks = exynos4210_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos4210_pin_banks2),
- .base = EXYNOS4210_GPIOA_NR_PINS +
- EXYNOS4210_GPIOB_NR_PINS,
- .nr_pins = EXYNOS4210_GPIOC_NR_PINS,
.label = "exynos4210-gpio-ctrl2",
},
};
+
+/* pin banks of exynos4x12 pin-controller 0 */
+static struct samsung_pin_bank exynos4x12_pin_banks0[] = {
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+ EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+ EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+ EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+ EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+ EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+ EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+ EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x40),
+ EXYNOS_PIN_BANK_EINTG(5, 0x260, "gpj1", 0x44),
+};
+
+/* pin banks of exynos4x12 pin-controller 1 */
+static struct samsung_pin_bank exynos4x12_pin_banks1[] = {
+ EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+ EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+ EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+ EXYNOS_PIN_BANK_EINTG(7, 0x0C0, "gpl0", 0x18),
+ EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpl1", 0x1c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
+ EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24),
+ EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28),
+ EXYNOS_PIN_BANK_EINTG(5, 0x2A0, "gpm2", 0x2c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x2C0, "gpm3", 0x30),
+ EXYNOS_PIN_BANK_EINTG(8, 0x2E0, "gpm4", 0x34),
+ EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
+ EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
+ EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos4x12 pin-controller 2 */
+static struct samsung_pin_bank exynos4x12_pin_banks2[] = {
+ EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/* pin banks of exynos4x12 pin-controller 3 */
+static struct samsung_pin_bank exynos4x12_pin_banks3[] = {
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpv2", 0x08),
+ EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv3", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpv4", 0x10),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos4x12 SoC. Exynos4x12 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
+ {
+ /* pin-controller instance 0 data */
+ .pin_banks = exynos4x12_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks0),
+ .geint_con = EXYNOS_GPIO_ECON_OFFSET,
+ .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+ .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
+ .svc = EXYNOS_SVC_OFFSET,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .label = "exynos4x12-gpio-ctrl0",
+ }, {
+ /* pin-controller instance 1 data */
+ .pin_banks = exynos4x12_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks1),
+ .geint_con = EXYNOS_GPIO_ECON_OFFSET,
+ .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+ .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
+ .weint_con = EXYNOS_WKUP_ECON_OFFSET,
+ .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
+ .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
+ .svc = EXYNOS_SVC_OFFSET,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .label = "exynos4x12-gpio-ctrl1",
+ }, {
+ /* pin-controller instance 2 data */
+ .pin_banks = exynos4x12_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks2),
+ .geint_con = EXYNOS_GPIO_ECON_OFFSET,
+ .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+ .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
+ .svc = EXYNOS_SVC_OFFSET,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .label = "exynos4x12-gpio-ctrl2",
+ }, {
+ /* pin-controller instance 3 data */
+ .pin_banks = exynos4x12_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks3),
+ .geint_con = EXYNOS_GPIO_ECON_OFFSET,
+ .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+ .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
+ .svc = EXYNOS_SVC_OFFSET,
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .label = "exynos4x12-gpio-ctrl3",
+ },
+};
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index 31d0a06174e..0a708890d8b 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -17,125 +17,6 @@
* (at your option) any later version.
*/
-#define EXYNOS_GPIO_START(__gpio) ((__gpio##_START) + (__gpio##_NR))
-
-#define EXYNOS4210_GPIO_A0_NR (8)
-#define EXYNOS4210_GPIO_A1_NR (6)
-#define EXYNOS4210_GPIO_B_NR (8)
-#define EXYNOS4210_GPIO_C0_NR (5)
-#define EXYNOS4210_GPIO_C1_NR (5)
-#define EXYNOS4210_GPIO_D0_NR (4)
-#define EXYNOS4210_GPIO_D1_NR (4)
-#define EXYNOS4210_GPIO_E0_NR (5)
-#define EXYNOS4210_GPIO_E1_NR (8)
-#define EXYNOS4210_GPIO_E2_NR (6)
-#define EXYNOS4210_GPIO_E3_NR (8)
-#define EXYNOS4210_GPIO_E4_NR (8)
-#define EXYNOS4210_GPIO_F0_NR (8)
-#define EXYNOS4210_GPIO_F1_NR (8)
-#define EXYNOS4210_GPIO_F2_NR (8)
-#define EXYNOS4210_GPIO_F3_NR (6)
-#define EXYNOS4210_GPIO_J0_NR (8)
-#define EXYNOS4210_GPIO_J1_NR (5)
-#define EXYNOS4210_GPIO_K0_NR (7)
-#define EXYNOS4210_GPIO_K1_NR (7)
-#define EXYNOS4210_GPIO_K2_NR (7)
-#define EXYNOS4210_GPIO_K3_NR (7)
-#define EXYNOS4210_GPIO_L0_NR (8)
-#define EXYNOS4210_GPIO_L1_NR (3)
-#define EXYNOS4210_GPIO_L2_NR (8)
-#define EXYNOS4210_GPIO_Y0_NR (6)
-#define EXYNOS4210_GPIO_Y1_NR (4)
-#define EXYNOS4210_GPIO_Y2_NR (6)
-#define EXYNOS4210_GPIO_Y3_NR (8)
-#define EXYNOS4210_GPIO_Y4_NR (8)
-#define EXYNOS4210_GPIO_Y5_NR (8)
-#define EXYNOS4210_GPIO_Y6_NR (8)
-#define EXYNOS4210_GPIO_X0_NR (8)
-#define EXYNOS4210_GPIO_X1_NR (8)
-#define EXYNOS4210_GPIO_X2_NR (8)
-#define EXYNOS4210_GPIO_X3_NR (8)
-#define EXYNOS4210_GPIO_Z_NR (7)
-
-enum exynos4210_gpio_xa_start {
- EXYNOS4210_GPIO_A0_START = 0,
- EXYNOS4210_GPIO_A1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A0),
- EXYNOS4210_GPIO_B_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A1),
- EXYNOS4210_GPIO_C0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_B),
- EXYNOS4210_GPIO_C1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C0),
- EXYNOS4210_GPIO_D0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C1),
- EXYNOS4210_GPIO_D1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D0),
- EXYNOS4210_GPIO_E0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D1),
- EXYNOS4210_GPIO_E1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E0),
- EXYNOS4210_GPIO_E2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E1),
- EXYNOS4210_GPIO_E3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E2),
- EXYNOS4210_GPIO_E4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E3),
- EXYNOS4210_GPIO_F0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E4),
- EXYNOS4210_GPIO_F1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F0),
- EXYNOS4210_GPIO_F2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F1),
- EXYNOS4210_GPIO_F3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F2),
-};
-
-enum exynos4210_gpio_xb_start {
- EXYNOS4210_GPIO_J0_START = 0,
- EXYNOS4210_GPIO_J1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J0),
- EXYNOS4210_GPIO_K0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J1),
- EXYNOS4210_GPIO_K1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K0),
- EXYNOS4210_GPIO_K2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K1),
- EXYNOS4210_GPIO_K3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K2),
- EXYNOS4210_GPIO_L0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K3),
- EXYNOS4210_GPIO_L1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L0),
- EXYNOS4210_GPIO_L2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L1),
- EXYNOS4210_GPIO_Y0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2),
- EXYNOS4210_GPIO_Y1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y0),
- EXYNOS4210_GPIO_Y2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y1),
- EXYNOS4210_GPIO_Y3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y2),
- EXYNOS4210_GPIO_Y4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y3),
- EXYNOS4210_GPIO_Y5_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y4),
- EXYNOS4210_GPIO_Y6_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y5),
- EXYNOS4210_GPIO_X0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y6),
- EXYNOS4210_GPIO_X1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X0),
- EXYNOS4210_GPIO_X2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X1),
- EXYNOS4210_GPIO_X3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X2),
-};
-
-enum exynos4210_gpio_xc_start {
- EXYNOS4210_GPIO_Z_START = 0,
-};
-
-#define EXYNOS4210_GPIO_A0_IRQ EXYNOS4210_GPIO_A0_START
-#define EXYNOS4210_GPIO_A1_IRQ EXYNOS4210_GPIO_A1_START
-#define EXYNOS4210_GPIO_B_IRQ EXYNOS4210_GPIO_B_START
-#define EXYNOS4210_GPIO_C0_IRQ EXYNOS4210_GPIO_C0_START
-#define EXYNOS4210_GPIO_C1_IRQ EXYNOS4210_GPIO_C1_START
-#define EXYNOS4210_GPIO_D0_IRQ EXYNOS4210_GPIO_D0_START
-#define EXYNOS4210_GPIO_D1_IRQ EXYNOS4210_GPIO_D1_START
-#define EXYNOS4210_GPIO_E0_IRQ EXYNOS4210_GPIO_E0_START
-#define EXYNOS4210_GPIO_E1_IRQ EXYNOS4210_GPIO_E1_START
-#define EXYNOS4210_GPIO_E2_IRQ EXYNOS4210_GPIO_E2_START
-#define EXYNOS4210_GPIO_E3_IRQ EXYNOS4210_GPIO_E3_START
-#define EXYNOS4210_GPIO_E4_IRQ EXYNOS4210_GPIO_E4_START
-#define EXYNOS4210_GPIO_F0_IRQ EXYNOS4210_GPIO_F0_START
-#define EXYNOS4210_GPIO_F1_IRQ EXYNOS4210_GPIO_F1_START
-#define EXYNOS4210_GPIO_F2_IRQ EXYNOS4210_GPIO_F2_START
-#define EXYNOS4210_GPIO_F3_IRQ EXYNOS4210_GPIO_F3_START
-#define EXYNOS4210_GPIO_J0_IRQ EXYNOS4210_GPIO_J0_START
-#define EXYNOS4210_GPIO_J1_IRQ EXYNOS4210_GPIO_J1_START
-#define EXYNOS4210_GPIO_K0_IRQ EXYNOS4210_GPIO_K0_START
-#define EXYNOS4210_GPIO_K1_IRQ EXYNOS4210_GPIO_K1_START
-#define EXYNOS4210_GPIO_K2_IRQ EXYNOS4210_GPIO_K2_START
-#define EXYNOS4210_GPIO_K3_IRQ EXYNOS4210_GPIO_K3_START
-#define EXYNOS4210_GPIO_L0_IRQ EXYNOS4210_GPIO_L0_START
-#define EXYNOS4210_GPIO_L1_IRQ EXYNOS4210_GPIO_L1_START
-#define EXYNOS4210_GPIO_L2_IRQ EXYNOS4210_GPIO_L2_START
-#define EXYNOS4210_GPIO_Z_IRQ EXYNOS4210_GPIO_Z_START
-
-#define EXYNOS4210_GPIOA_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
-#define EXYNOS4210_GPIOA_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3)
-#define EXYNOS4210_GPIOB_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3)
-#define EXYNOS4210_GPIOB_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2)
-#define EXYNOS4210_GPIOC_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z)
-
/* External GPIO and wakeup interrupt related definitions */
#define EXYNOS_GPIO_ECON_OFFSET 0x700
#define EXYNOS_GPIO_EMASK_OFFSET 0x900
@@ -165,11 +46,10 @@ enum exynos4210_gpio_xc_start {
#define EXYNOS_EINT_MAX_PER_BANK 8
#define EXYNOS_EINT_NR_WKUP_EINT
-#define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id) \
+#define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \
{ \
.pctl_offset = reg, \
- .pin_base = (__gpio##_START), \
- .nr_pins = (__gpio##_NR), \
+ .nr_pins = pins, \
.func_width = 4, \
.pud_width = 2, \
.drv_width = 2, \
@@ -179,40 +59,50 @@ enum exynos4210_gpio_xc_start {
.name = id \
}
-#define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id) \
+#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \
{ \
.pctl_offset = reg, \
- .pin_base = (__gpio##_START), \
- .nr_pins = (__gpio##_NR), \
+ .nr_pins = pins, \
.func_width = 4, \
.pud_width = 2, \
.drv_width = 2, \
.conpdn_width = 2, \
.pudpdn_width = 2, \
.eint_type = EINT_TYPE_GPIO, \
- .irq_base = (__gpio##_IRQ), \
+ .eint_offset = offs, \
.name = id \
}
-/**
- * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
- * @bank: pin bank from which this gpio interrupt originates.
- * @pin: pin number within the bank.
- * @eint_offset: offset to be added to the con/pend/mask register bank base.
- */
-struct exynos_geint_data {
- struct samsung_pin_bank *bank;
- u32 pin;
- u32 eint_offset;
-};
+#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \
+ { \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .func_width = 4, \
+ .pud_width = 2, \
+ .drv_width = 2, \
+ .eint_type = EINT_TYPE_WKUP, \
+ .eint_offset = offs, \
+ .name = id \
+ }
/**
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
* generated by the external wakeup interrupt controller.
- * @domain: irq domain representing the external wakeup interrupts
* @irq: interrupt number within the domain.
+ * @bank: bank responsible for this interrupt
*/
struct exynos_weint_data {
- struct irq_domain *domain;
- u32 irq;
+ unsigned int irq;
+ struct samsung_pin_bank *bank;
+};
+
+/**
+ * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts
+ * generated by the external wakeup interrupt controller.
+ * @nr_banks: count of banks being part of the mux
+ * @banks: array of banks being part of the mux
+ */
+struct exynos_muxed_weint_data {
+ unsigned int nr_banks;
+ struct samsung_pin_bank *banks[];
};
diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/pinctrl-kirkwood.c
deleted file mode 100644
index 9a74ef674a0..00000000000
--- a/drivers/pinctrl/pinctrl-kirkwood.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
- *
- * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include "pinctrl-mvebu.h"
-
-#define V(f6180, f6190, f6192, f6281, f6282) \
- ((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
- (f6281 << 3) | (f6282 << 4))
-
-enum kirkwood_variant {
- VARIANT_MV88F6180 = V(1, 0, 0, 0, 0),
- VARIANT_MV88F6190 = V(0, 1, 0, 0, 0),
- VARIANT_MV88F6192 = V(0, 0, 1, 0, 0),
- VARIANT_MV88F6281 = V(0, 0, 0, 1, 0),
- VARIANT_MV88F6282 = V(0, 0, 0, 0, 1),
-};
-
-static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
- MPP_MODE(0,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1))),
- MPP_MODE(1,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1))),
- MPP_MODE(2,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1))),
- MPP_MODE(3,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1))),
- MPP_MODE(4,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0))),
- MPP_MODE(5,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))),
- MPP_MODE(6,
- MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0))),
- MPP_MODE(7,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))),
- MPP_MODE(8,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))),
- MPP_MODE(9,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))),
- MPP_MODE(10,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0))),
- MPP_MODE(11,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1))),
- MPP_MODE(12,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1)),
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1))),
- MPP_MODE(13,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))),
- MPP_MODE(14,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))),
- MPP_MODE(15,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1))),
- MPP_MODE(16,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))),
- MPP_MODE(17,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1))),
- MPP_MODE(18,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1))),
- MPP_MODE(19,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1))),
- MPP_MODE(20,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 0, 0, 0, 0))),
- MPP_MODE(21,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1))),
- MPP_MODE(22,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1))),
- MPP_MODE(23,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1))),
- MPP_MODE(24,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1))),
- MPP_MODE(25,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1))),
- MPP_MODE(26,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1))),
- MPP_MODE(27,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1))),
- MPP_MODE(28,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1))),
- MPP_MODE(29,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1))),
- MPP_MODE(30,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1))),
- MPP_MODE(31,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1))),
- MPP_MODE(32,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1))),
- MPP_MODE(33,
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1))),
- MPP_MODE(34,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1))),
- MPP_MODE(35,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 1, 1, 1, 1))),
- MPP_MODE(36,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1))),
- MPP_MODE(37,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1))),
- MPP_MODE(38,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1))),
- MPP_MODE(39,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1))),
- MPP_MODE(40,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1))),
- MPP_MODE(41,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1))),
- MPP_MODE(42,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1))),
- MPP_MODE(43,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1))),
- MPP_MODE(44,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1))),
- MPP_MODE(45,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1))),
- MPP_MODE(46,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1))),
- MPP_MODE(47,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))),
- MPP_MODE(48,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1))),
- MPP_MODE(49,
- MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1)),
- MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0)),
- MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1)),
- MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1))),
-};
-
-static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
- MPP_REG_CTRL(0, 29),
-};
-
-static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
- MPP_GPIO_RANGE(0, 0, 0, 30),
-};
-
-static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
- MPP_REG_CTRL(0, 35),
-};
-
-static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
- MPP_GPIO_RANGE(0, 0, 0, 32),
- MPP_GPIO_RANGE(1, 32, 32, 4),
-};
-
-static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
- MPP_REG_CTRL(0, 49),
-};
-
-static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
- MPP_GPIO_RANGE(0, 0, 0, 32),
- MPP_GPIO_RANGE(1, 32, 32, 18),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6180_info = {
- .variant = VARIANT_MV88F6180,
- .controls = mv88f6180_mpp_controls,
- .ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
- .modes = mv88f6xxx_mpp_modes,
- .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
- .gpioranges = mv88f6180_gpio_ranges,
- .ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6190_info = {
- .variant = VARIANT_MV88F6190,
- .controls = mv88f619x_mpp_controls,
- .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
- .modes = mv88f6xxx_mpp_modes,
- .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
- .gpioranges = mv88f619x_gpio_ranges,
- .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6192_info = {
- .variant = VARIANT_MV88F6192,
- .controls = mv88f619x_mpp_controls,
- .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
- .modes = mv88f6xxx_mpp_modes,
- .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
- .gpioranges = mv88f619x_gpio_ranges,
- .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6281_info = {
- .variant = VARIANT_MV88F6281,
- .controls = mv88f628x_mpp_controls,
- .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
- .modes = mv88f6xxx_mpp_modes,
- .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
- .gpioranges = mv88f628x_gpio_ranges,
- .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
-};
-
-static struct mvebu_pinctrl_soc_info mv88f6282_info = {
- .variant = VARIANT_MV88F6282,
- .controls = mv88f628x_mpp_controls,
- .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
- .modes = mv88f6xxx_mpp_modes,
- .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
- .gpioranges = mv88f628x_gpio_ranges,
- .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
-};
-
-static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
- { .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
- { .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
- { .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
- { .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
- { .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
- { }
-};
-
-static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
-{
- const struct of_device_id *match =
- of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
- pdev->dev.platform_data = match->data;
- return mvebu_pinctrl_probe(pdev);
-}
-
-static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
-{
- return mvebu_pinctrl_remove(pdev);
-}
-
-static struct platform_driver kirkwood_pinctrl_driver = {
- .driver = {
- .name = "kirkwood-pinctrl",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
- },
- .probe = kirkwood_pinctrl_probe,
- .remove = __devexit_p(kirkwood_pinctrl_remove),
-};
-
-module_platform_driver(kirkwood_pinctrl_driver);
-
-MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
-MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 861cd5f04d5..81c9896d4f6 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/irqdomain.h>
#include "core.h"
#include "pinctrl-samsung.h"
@@ -46,6 +47,13 @@ struct pin_config {
{ "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
};
+static unsigned int pin_base = 0;
+
+static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
+{
+ return container_of(gc, struct samsung_pin_bank, gpio_chip);
+}
+
/* check if the selector is a valid pin group selector */
static int samsung_get_group_count(struct pinctrl_dev *pctldev)
{
@@ -250,14 +258,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,
* given a pin number that is local to a pin controller, find out the pin bank
* and the register base of the pin bank.
*/
-static void pin_to_reg_bank(struct gpio_chip *gc, unsigned pin,
- void __iomem **reg, u32 *offset,
+static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata,
+ unsigned pin, void __iomem **reg, u32 *offset,
struct samsung_pin_bank **bank)
{
- struct samsung_pinctrl_drv_data *drvdata;
struct samsung_pin_bank *b;
- drvdata = dev_get_drvdata(gc->dev);
b = drvdata->ctrl->pin_banks;
while ((pin >= b->pin_base) &&
@@ -292,7 +298,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
* pin function number in the config register.
*/
for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
- pin_to_reg_bank(drvdata->gc, pins[cnt] - drvdata->ctrl->base,
+ pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
&reg, &pin_offset, &bank);
mask = (1 << bank->func_width) - 1;
shift = pin_offset * bank->func_width;
@@ -329,10 +335,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset, bool input)
{
struct samsung_pin_bank *bank;
+ struct samsung_pinctrl_drv_data *drvdata;
void __iomem *reg;
u32 data, pin_offset, mask, shift;
- pin_to_reg_bank(range->gc, offset, &reg, &pin_offset, &bank);
+ bank = gc_to_pin_bank(range->gc);
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+
+ pin_offset = offset - bank->pin_base;
+ reg = drvdata->virt_base + bank->pctl_offset;
+
mask = (1 << bank->func_width) - 1;
shift = pin_offset * bank->func_width;
@@ -366,7 +378,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
u32 cfg_value, cfg_reg;
drvdata = pinctrl_dev_get_drvdata(pctldev);
- pin_to_reg_bank(drvdata->gc, pin - drvdata->ctrl->base, &reg_base,
+ pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
&pin_offset, &bank);
switch (cfg_type) {
@@ -391,6 +403,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
return -EINVAL;
}
+ if (!width)
+ return -EINVAL;
+
mask = (1 << width) - 1;
shift = pin_offset * width;
data = readl(reg_base + cfg_reg);
@@ -463,14 +478,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
/* gpiolib gpio_set callback function */
static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
{
+ struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
void __iomem *reg;
- u32 pin_offset, data;
+ u32 data;
+
+ reg = bank->drvdata->virt_base + bank->pctl_offset;
- pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
data = readl(reg + DAT_REG);
- data &= ~(1 << pin_offset);
+ data &= ~(1 << offset);
if (value)
- data |= 1 << pin_offset;
+ data |= 1 << offset;
writel(data, reg + DAT_REG);
}
@@ -478,11 +495,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
{
void __iomem *reg;
- u32 pin_offset, data;
+ u32 data;
+ struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+
+ reg = bank->drvdata->virt_base + bank->pctl_offset;
- pin_to_reg_bank(gc, offset, &reg, &pin_offset, NULL);
data = readl(reg + DAT_REG);
- data >>= pin_offset;
+ data >>= offset;
data &= 1;
return data;
}
@@ -510,6 +529,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
}
/*
+ * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
+ * and a virtual IRQ, if not already present.
+ */
+static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+ struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+ unsigned int virq;
+
+ if (!bank->irq_domain)
+ return -ENXIO;
+
+ virq = irq_create_mapping(bank->irq_domain, offset);
+
+ return (virq) ? : -ENXIO;
+}
+
+/*
* Parse the pin names listed in the 'samsung,pins' property and convert it
* into a list of gpio numbers are create a pin group from it.
*/
@@ -597,7 +633,7 @@ static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
*/
for_each_child_of_node(dev_np, cfg_np) {
u32 function;
- if (of_find_property(cfg_np, "interrupt-controller", NULL))
+ if (!of_find_property(cfg_np, "samsung,pins", NULL))
continue;
ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
@@ -712,12 +748,16 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
return -EINVAL;
}
- drvdata->grange.name = "samsung-pctrl-gpio-range";
- drvdata->grange.id = 0;
- drvdata->grange.base = drvdata->ctrl->base;
- drvdata->grange.npins = drvdata->ctrl->nr_pins;
- drvdata->grange.gc = drvdata->gc;
- pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange);
+ for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
+ pin_bank = &drvdata->ctrl->pin_banks[bank];
+ pin_bank->grange.name = pin_bank->name;
+ pin_bank->grange.id = bank;
+ pin_bank->grange.pin_base = pin_bank->pin_base;
+ pin_bank->grange.base = pin_bank->gpio_chip.base;
+ pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
+ pin_bank->grange.gc = &pin_bank->gpio_chip;
+ pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
+ }
ret = samsung_pinctrl_parse_dt(pdev, drvdata);
if (ret) {
@@ -728,68 +768,117 @@ static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
return 0;
}
+static const struct gpio_chip samsung_gpiolib_chip = {
+ .set = samsung_gpio_set,
+ .get = samsung_gpio_get,
+ .direction_input = samsung_gpio_direction_input,
+ .direction_output = samsung_gpio_direction_output,
+ .to_irq = samsung_gpio_to_irq,
+ .owner = THIS_MODULE,
+};
+
/* register the gpiolib interface with the gpiolib subsystem */
static int __devinit samsung_gpiolib_register(struct platform_device *pdev,
struct samsung_pinctrl_drv_data *drvdata)
{
+ struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+ struct samsung_pin_bank *bank = ctrl->pin_banks;
struct gpio_chip *gc;
int ret;
-
- gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
- if (!gc) {
- dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
- return -ENOMEM;
- }
-
- drvdata->gc = gc;
- gc->base = drvdata->ctrl->base;
- gc->ngpio = drvdata->ctrl->nr_pins;
- gc->dev = &pdev->dev;
- gc->set = samsung_gpio_set;
- gc->get = samsung_gpio_get;
- gc->direction_input = samsung_gpio_direction_input;
- gc->direction_output = samsung_gpio_direction_output;
- gc->label = drvdata->ctrl->label;
- gc->owner = THIS_MODULE;
- ret = gpiochip_add(gc);
- if (ret) {
- dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
- "code: %d\n", gc->label, ret);
- return ret;
+ int i;
+
+ for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+ bank->gpio_chip = samsung_gpiolib_chip;
+
+ gc = &bank->gpio_chip;
+ gc->base = ctrl->base + bank->pin_base;
+ gc->ngpio = bank->nr_pins;
+ gc->dev = &pdev->dev;
+ gc->of_node = bank->of_node;
+ gc->label = bank->name;
+
+ ret = gpiochip_add(gc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
+ gc->label, ret);
+ goto fail;
+ }
}
return 0;
+
+fail:
+ for (--i, --bank; i >= 0; --i, --bank)
+ if (gpiochip_remove(&bank->gpio_chip))
+ dev_err(&pdev->dev, "gpio chip %s remove failed\n",
+ bank->gpio_chip.label);
+ return ret;
}
/* unregister the gpiolib interface with the gpiolib subsystem */
static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev,
struct samsung_pinctrl_drv_data *drvdata)
{
- int ret = gpiochip_remove(drvdata->gc);
- if (ret) {
+ struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+ struct samsung_pin_bank *bank = ctrl->pin_banks;
+ int ret = 0;
+ int i;
+
+ for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
+ ret = gpiochip_remove(&bank->gpio_chip);
+
+ if (ret)
dev_err(&pdev->dev, "gpio chip remove failed\n");
- return ret;
- }
- return 0;
+
+ return ret;
}
static const struct of_device_id samsung_pinctrl_dt_match[];
/* retrieve the soc specific data */
static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
+ struct samsung_pinctrl_drv_data *d,
struct platform_device *pdev)
{
int id;
const struct of_device_id *match;
- const struct device_node *node = pdev->dev.of_node;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *np;
+ struct samsung_pin_ctrl *ctrl;
+ struct samsung_pin_bank *bank;
+ int i;
- id = of_alias_get_id(pdev->dev.of_node, "pinctrl");
+ id = of_alias_get_id(node, "pinctrl");
if (id < 0) {
dev_err(&pdev->dev, "failed to get alias id\n");
return NULL;
}
match = of_match_node(samsung_pinctrl_dt_match, node);
- return (struct samsung_pin_ctrl *)match->data + id;
+ ctrl = (struct samsung_pin_ctrl *)match->data + id;
+
+ bank = ctrl->pin_banks;
+ for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+ bank->drvdata = d;
+ bank->pin_base = ctrl->nr_pins;
+ ctrl->nr_pins += bank->nr_pins;
+ }
+
+ for_each_child_of_node(node, np) {
+ if (!of_find_property(np, "gpio-controller", NULL))
+ continue;
+ bank = ctrl->pin_banks;
+ for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+ if (!strcmp(bank->name, np->name)) {
+ bank->of_node = np;
+ break;
+ }
+ }
+ }
+
+ ctrl->base = pin_base;
+ pin_base += ctrl->nr_pins;
+
+ return ctrl;
}
static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
@@ -805,18 +894,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
return -ENODEV;
}
- ctrl = samsung_pinctrl_get_soc_data(pdev);
- if (!ctrl) {
- dev_err(&pdev->dev, "driver data not available\n");
- return -EINVAL;
- }
-
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata) {
dev_err(dev, "failed to allocate memory for driver's "
"private data\n");
return -ENOMEM;
}
+
+ ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
+ if (!ctrl) {
+ dev_err(&pdev->dev, "driver data not available\n");
+ return -EINVAL;
+ }
drvdata->ctrl = ctrl;
drvdata->dev = dev;
@@ -858,6 +947,8 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
static const struct of_device_id samsung_pinctrl_dt_match[] = {
{ .compatible = "samsung,pinctrl-exynos4210",
.data = (void *)exynos4210_pin_ctrl },
+ { .compatible = "samsung,pinctrl-exynos4x12",
+ .data = (void *)exynos4x12_pin_ctrl },
{},
};
MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index b8956934cda..5addfd16e3c 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -23,6 +23,8 @@
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/machine.h>
+#include <linux/gpio.h>
+
/* register offsets within a pin bank */
#define DAT_REG 0x4
#define PUD_REG 0x8
@@ -64,6 +66,7 @@ enum pincfg_type {
* @EINT_TYPE_NONE: bank does not support external interrupts
* @EINT_TYPE_GPIO: bank supportes external gpio interrupts
* @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
+ * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts
*
* Samsung GPIO controller groups all the available pins into banks. The pins
* in a pin bank can support external gpio interrupts or external wakeup
@@ -76,6 +79,7 @@ enum eint_type {
EINT_TYPE_NONE,
EINT_TYPE_GPIO,
EINT_TYPE_WKUP,
+ EINT_TYPE_WKUP_MUX,
};
/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
@@ -109,8 +113,12 @@ struct samsung_pinctrl_drv_data;
* @conpdn_width: width of the sleep mode function selector bin field.
* @pudpdn_width: width of the sleep mode pull up/down selector bit field.
* @eint_type: type of the external interrupt supported by the bank.
- * @irq_base: starting controller local irq number of the bank.
* @name: name to be prefixed for each pin in this pin bank.
+ * @of_node: OF node of the bank.
+ * @drvdata: link to controller driver data
+ * @irq_domain: IRQ domain of the bank.
+ * @gpio_chip: GPIO chip of the bank.
+ * @grange: linux gpio pin range supported by this bank.
*/
struct samsung_pin_bank {
u32 pctl_offset;
@@ -122,8 +130,13 @@ struct samsung_pin_bank {
u8 conpdn_width;
u8 pudpdn_width;
enum eint_type eint_type;
- u32 irq_base;
+ u32 eint_offset;
char *name;
+ struct device_node *of_node;
+ struct samsung_pinctrl_drv_data *drvdata;
+ struct irq_domain *irq_domain;
+ struct gpio_chip gpio_chip;
+ struct pinctrl_gpio_range grange;
};
/**
@@ -132,8 +145,6 @@ struct samsung_pin_bank {
* @nr_banks: number of pin banks.
* @base: starting system wide pin number.
* @nr_pins: number of pins supported by the controller.
- * @nr_gint: number of external gpio interrupts supported.
- * @nr_wint: number of external wakeup interrupts supported.
* @geint_con: offset of the ext-gpio controller registers.
* @geint_mask: offset of the ext-gpio interrupt mask registers.
* @geint_pend: offset of the ext-gpio interrupt pending registers.
@@ -153,8 +164,6 @@ struct samsung_pin_ctrl {
u32 base;
u32 nr_pins;
- u32 nr_gint;
- u32 nr_wint;
u32 geint_con;
u32 geint_mask;
@@ -183,8 +192,6 @@ struct samsung_pin_ctrl {
* @nr_groups: number of such pin groups.
* @pmx_functions: list of pin functions available to the driver.
* @nr_function: number of such pin functions.
- * @gc: gpio_chip instance registered with gpiolib.
- * @grange: linux gpio pin range supported by this controller.
*/
struct samsung_pinctrl_drv_data {
void __iomem *virt_base;
@@ -199,12 +206,6 @@ struct samsung_pinctrl_drv_data {
unsigned int nr_groups;
const struct samsung_pmx_func *pmx_functions;
unsigned int nr_functions;
-
- struct irq_domain *gpio_irqd;
- struct irq_domain *wkup_irqd;
-
- struct gpio_chip *gc;
- struct pinctrl_gpio_range grange;
};
/**
@@ -235,5 +236,6 @@ struct samsung_pmx_func {
/* list of all exported SoC specific data */
extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
#endif /* __PINCTRL_SAMSUNG_H */
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 9301a7a95ef..0ef01ee2835 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
char const * const *groups;
unsigned num_groups;
int ret;
const char *group;
int i;
- const unsigned *pins;
- unsigned num_pins;
if (!pmxops) {
dev_err(pctldev->dev, "does not support mux function\n");
@@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
}
setting->data.mux.group = ret;
- ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
- &num_pins);
- if (ret) {
- dev_err(pctldev->dev,
- "could not get pins for device %s group selector %d\n",
- pinctrl_dev_get_name(pctldev), setting->data.mux.group);
- return -ENODEV;
- }
-
- /* Try to allocate all pins in this group, one by one */
- for (i = 0; i < num_pins; i++) {
- ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
- if (ret) {
- dev_err(pctldev->dev,
- "could not request pin %d on device %s\n",
- pins[i], pinctrl_dev_get_name(pctldev));
- /* On error release all taken pins */
- i--; /* this pin just failed */
- for (; i >= 0; i--)
- pin_free(pctldev, pins[i], NULL);
- return -ENODEV;
- }
- }
-
return 0;
}
void pinmux_free_setting(struct pinctrl_setting const *setting)
{
- struct pinctrl_dev *pctldev = setting->pctldev;
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const unsigned *pins;
- unsigned num_pins;
- int ret;
- int i;
-
- ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
- &pins, &num_pins);
- if (ret) {
- dev_err(pctldev->dev,
- "could not get pins for device %s group selector %d\n",
- pinctrl_dev_get_name(pctldev), setting->data.mux.group);
- return;
- }
-
- for (i = 0; i < num_pins; i++)
- pin_free(pctldev, pins[i], NULL);
+ /* This function is currently unused */
}
int pinmux_enable_setting(struct pinctrl_setting const *setting)
@@ -446,6 +402,22 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
num_pins = 0;
}
+ /* Try to allocate all pins in this group, one by one */
+ for (i = 0; i < num_pins; i++) {
+ ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
+ if (ret) {
+ dev_err(pctldev->dev,
+ "could not request pin %d on device %s\n",
+ pins[i], pinctrl_dev_get_name(pctldev));
+ /* On error release all taken pins */
+ i--; /* this pin just failed */
+ for (; i >= 0; i--)
+ pin_free(pctldev, pins[i], NULL);
+ return -ENODEV;
+ }
+ }
+
+ /* Now that we have acquired the pins, encode the mux setting */
for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) {
@@ -482,6 +454,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
num_pins = 0;
}
+ /* Flag the descs that no setting is active */
for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) {
@@ -493,6 +466,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
desc->mux_setting = NULL;
}
+ /* And release the pins */
+ for (i = 0; i < num_pins; i++)
+ pin_free(pctldev, pins[i], NULL);
+
if (ops->disable)
ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
}
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 5d4f44f462f..b1fd6ee33c6 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -244,7 +244,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
else
temp = ~muxreg->val;
- val |= temp;
+ val |= muxreg->mask & temp;
pmx_writel(pmx, val, muxreg->reg);
}
}
diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index d6cca8c81b9..0436fc7895d 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
};
/* registers */
-#define PERIP_CFG 0x32C
- #define MCIF_SEL_SHIFT 3
+#define PERIP_CFG 0x3B0
+ #define MCIF_SEL_SHIFT 5
#define MCIF_SEL_SD (0x1 << MCIF_SEL_SHIFT)
#define MCIF_SEL_CF (0x2 << MCIF_SEL_SHIFT)
#define MCIF_SEL_XD (0x3 << MCIF_SEL_SHIFT)
@@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
#define PMX_SSP0_CS0_MASK (1 << 29)
#define PMX_SSP0_CS1_2_MASK (1 << 30)
+#define PAD_DIRECTION_SEL_0 0x65C
+#define PAD_DIRECTION_SEL_1 0x660
+#define PAD_DIRECTION_SEL_2 0x664
+
/* combined macros */
#define PMX_GMII_MASK (PMX_GMIICLK_MASK | \
PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK | \
@@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_I2C0_MASK,
.val = PMX_I2C0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_I2C0_MASK,
+ .val = PMX_I2C0_MASK,
},
};
@@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_SSP0_MASK,
.val = PMX_SSP0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_SSP0_MASK,
+ .val = PMX_SSP0_MASK,
},
};
@@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = {
.reg = PAD_FUNCTION_EN_2,
.mask = PMX_SSP0_CS0_MASK,
.val = PMX_SSP0_CS0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_SSP0_CS0_MASK,
+ .val = PMX_SSP0_CS0_MASK,
},
};
@@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = {
.reg = PAD_FUNCTION_EN_2,
.mask = PMX_SSP0_CS1_2_MASK,
.val = PMX_SSP0_CS1_2_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_SSP0_CS1_2_MASK,
+ .val = PMX_SSP0_CS1_2_MASK,
},
};
@@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_I2S0_MASK,
.val = PMX_I2S0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_I2S0_MASK,
+ .val = PMX_I2S0_MASK,
},
};
@@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_I2S1_MASK,
.val = PMX_I2S1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_I2S1_MASK,
+ .val = PMX_I2S1_MASK,
},
};
@@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_CLCD1_MASK,
.val = PMX_CLCD1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_CLCD1_MASK,
+ .val = PMX_CLCD1_MASK,
},
};
@@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_CLCD2_MASK,
.val = PMX_CLCD2_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_CLCD2_MASK,
+ .val = PMX_CLCD2_MASK,
},
};
@@ -461,7 +497,7 @@ static struct spear_pingroup clcd_high_res_pingroup = {
.nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux),
};
-static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" };
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" };
static struct spear_function clcd_function = {
.name = "clcd",
.groups = clcd_grps,
@@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_EGPIO_1_GRP_MASK,
.val = PMX_EGPIO_1_GRP_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_EGPIO_0_GRP_MASK,
+ .val = PMX_EGPIO_0_GRP_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_EGPIO_1_GRP_MASK,
+ .val = PMX_EGPIO_1_GRP_MASK,
},
};
@@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_SMI_MASK,
.val = PMX_SMI_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_SMI_MASK,
+ .val = PMX_SMI_MASK,
},
};
@@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
.val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_SMI_MASK,
+ .val = PMX_SMI_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+ .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
},
};
@@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_GMII_MASK,
.val = PMX_GMII_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_GMII_MASK,
+ .val = PMX_GMII_MASK,
},
};
@@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = {
.reg = PAD_FUNCTION_EN_2,
.mask = PMX_RGMII_REG2_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_RGMII_REG0_MASK,
+ .val = PMX_RGMII_REG0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_RGMII_REG1_MASK,
+ .val = PMX_RGMII_REG1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_RGMII_REG2_MASK,
+ .val = PMX_RGMII_REG2_MASK,
},
};
@@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_SMII_0_1_2_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_SMII_0_1_2_MASK,
+ .val = PMX_SMII_0_1_2_MASK,
},
};
@@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_NFCE2_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_NFCE2_MASK,
+ .val = PMX_NFCE2_MASK,
},
};
@@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_NAND8BIT_1_MASK,
.val = PMX_NAND8BIT_1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_NAND8BIT_0_MASK,
+ .val = PMX_NAND8BIT_0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_NAND8BIT_1_MASK,
+ .val = PMX_NAND8BIT_1_MASK,
},
};
@@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_NAND16BIT_1_MASK,
.val = PMX_NAND16BIT_1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_NAND16BIT_1_MASK,
+ .val = PMX_NAND16BIT_1_MASK,
},
};
@@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_NAND_4CHIPS_MASK,
.val = PMX_NAND_4CHIPS_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_NAND_4CHIPS_MASK,
+ .val = PMX_NAND_4CHIPS_MASK,
},
};
@@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_KBD_ROWCOL68_MASK,
.val = PMX_KBD_ROWCOL68_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_KBD_ROWCOL68_MASK,
+ .val = PMX_KBD_ROWCOL68_MASK,
},
};
@@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_UART0_MASK,
.val = PMX_UART0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_UART0_MASK,
+ .val = PMX_UART0_MASK,
},
};
@@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_UART0_MODEM_MASK,
.val = PMX_UART0_MODEM_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_UART0_MODEM_MASK,
+ .val = PMX_UART0_MODEM_MASK,
},
};
@@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_GPT0_TMR0_MASK,
.val = PMX_GPT0_TMR0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_GPT0_TMR0_MASK,
+ .val = PMX_GPT0_TMR0_MASK,
},
};
@@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_GPT0_TMR1_MASK,
.val = PMX_GPT0_TMR1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_GPT0_TMR1_MASK,
+ .val = PMX_GPT0_TMR1_MASK,
},
};
@@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_GPT1_TMR0_MASK,
.val = PMX_GPT1_TMR0_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_GPT1_TMR0_MASK,
+ .val = PMX_GPT1_TMR0_MASK,
},
};
@@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_GPT1_TMR1_MASK,
.val = PMX_GPT1_TMR1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_GPT1_TMR1_MASK,
+ .val = PMX_GPT1_TMR1_MASK,
},
};
@@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214,
.reg = PAD_FUNCTION_EN_2, \
.mask = PMX_MCIFALL_2_MASK, \
.val = PMX_MCIFALL_2_MASK, \
+ }, { \
+ .reg = PAD_DIRECTION_SEL_0, \
+ .mask = PMX_MCI_DATA8_15_MASK, \
+ .val = PMX_MCI_DATA8_15_MASK, \
+ }, { \
+ .reg = PAD_DIRECTION_SEL_1, \
+ .mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \
+ PMX_NFWPRT2_MASK, \
+ .val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \
+ PMX_NFWPRT2_MASK, \
+ }, { \
+ .reg = PAD_DIRECTION_SEL_2, \
+ .mask = PMX_MCIFALL_2_MASK, \
+ .val = PMX_MCIFALL_2_MASK, \
}
/* sdhci device */
@@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = {
.reg = PAD_FUNCTION_EN_2,
.mask = PMX_TOUCH_XY_MASK,
.val = PMX_TOUCH_XY_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_TOUCH_XY_MASK,
+ .val = PMX_TOUCH_XY_MASK,
},
};
@@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_I2C0_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_I2C0_MASK,
+ .val = PMX_I2C0_MASK,
},
};
@@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = {
.mask = PMX_MCIDATA1_MASK |
PMX_MCIDATA2_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_MCIDATA1_MASK |
+ PMX_MCIDATA2_MASK,
+ .val = PMX_MCIDATA1_MASK |
+ PMX_MCIDATA2_MASK,
},
};
@@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_I2S0_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_I2S0_MASK,
+ .val = PMX_I2S0_MASK,
},
};
@@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
+ .val = PMX_I2S0_MASK | PMX_CLCD1_MASK,
},
};
@@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_CLCD1_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_CLCD1_MASK,
+ .val = PMX_CLCD1_MASK,
},
};
@@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_CLCD1_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_CLCD1_MASK,
+ .val = PMX_CLCD1_MASK,
},
};
@@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_CLCD1_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_CLCD1_MASK,
+ .val = PMX_CLCD1_MASK,
},
};
@@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
+ .val = PMX_CLCD1_MASK | PMX_SMI_MASK,
},
};
@@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
+ .val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
},
};
@@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = {
.reg = PAD_FUNCTION_EN_0,
.mask = PMX_SMI_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_SMI_MASK,
+ .val = PMX_SMI_MASK,
},
};
@@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = {
.reg = PAD_FUNCTION_EN_2,
.mask = PMX_MCIDATA5_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_MCIDATA4_MASK,
+ .val = PMX_MCIDATA4_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCIDATA5_MASK,
+ .val = PMX_MCIDATA5_MASK,
},
};
@@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = {
.mask = PMX_MCIDATA6_MASK |
PMX_MCIDATA7_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCIDATA6_MASK |
+ PMX_MCIDATA7_MASK,
+ .val = PMX_MCIDATA6_MASK |
+ PMX_MCIDATA7_MASK,
},
};
@@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_KBD_ROWCOL25_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_KBD_ROWCOL25_MASK,
+ .val = PMX_KBD_ROWCOL25_MASK,
},
};
@@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = {
.mask = PMX_MCIIORDRE_MASK |
PMX_MCIIOWRWE_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCIIORDRE_MASK |
+ PMX_MCIIOWRWE_MASK,
+ .val = PMX_MCIIORDRE_MASK |
+ PMX_MCIIOWRWE_MASK,
},
};
@@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = {
.mask = PMX_MCIRESETCF_MASK |
PMX_MCICS0CE_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCIRESETCF_MASK |
+ PMX_MCICS0CE_MASK,
+ .val = PMX_MCIRESETCF_MASK |
+ PMX_MCICS0CE_MASK,
},
};
@@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_NFRSTPWDWN3_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_NFRSTPWDWN2_MASK,
+ .val = PMX_NFRSTPWDWN2_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_NFRSTPWDWN3_MASK,
+ .val = PMX_NFRSTPWDWN3_MASK,
},
};
@@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = {
.reg = PAD_FUNCTION_EN_2,
.mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
+ .val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
},
};
@@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = {
.reg = PAD_FUNCTION_EN_2,
.mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
+ .val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
},
};
@@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = {
.reg = PAD_FUNCTION_EN_1,
.mask = PMX_KBD_ROWCOL25_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_KBD_ROWCOL25_MASK,
+ .val = PMX_KBD_ROWCOL25_MASK,
},
};
@@ -1763,29 +1997,64 @@ static struct spear_function can1_function = {
.ngroups = ARRAY_SIZE(can1_grps),
};
-/* Pad multiplexing for pci device */
-static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
+/* Pad multiplexing for (ras-ip) pci device */
+static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 };
-#define PCI_SATA_MUXREG \
- { \
- .reg = PAD_FUNCTION_EN_0, \
- .mask = PMX_MCI_DATA8_15_MASK, \
- .val = 0, \
- }, { \
- .reg = PAD_FUNCTION_EN_1, \
- .mask = PMX_PCI_REG1_MASK, \
- .val = 0, \
- }, { \
- .reg = PAD_FUNCTION_EN_2, \
- .mask = PMX_PCI_REG2_MASK, \
- .val = 0, \
- }
-/* pad multiplexing for pcie0 device */
+static struct spear_muxreg pci_muxreg[] = {
+ {
+ .reg = PAD_FUNCTION_EN_0,
+ .mask = PMX_MCI_DATA8_15_MASK,
+ .val = 0,
+ }, {
+ .reg = PAD_FUNCTION_EN_1,
+ .mask = PMX_PCI_REG1_MASK,
+ .val = 0,
+ }, {
+ .reg = PAD_FUNCTION_EN_2,
+ .mask = PMX_PCI_REG2_MASK,
+ .val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_0,
+ .mask = PMX_MCI_DATA8_15_MASK,
+ .val = PMX_MCI_DATA8_15_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_PCI_REG1_MASK,
+ .val = PMX_PCI_REG1_MASK,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_PCI_REG2_MASK,
+ .val = PMX_PCI_REG2_MASK,
+ },
+};
+
+static struct spear_modemux pci_modemux[] = {
+ {
+ .muxregs = pci_muxreg,
+ .nmuxregs = ARRAY_SIZE(pci_muxreg),
+ },
+};
+
+static struct spear_pingroup pci_pingroup = {
+ .name = "pci_grp",
+ .pins = pci_pins,
+ .npins = ARRAY_SIZE(pci_pins),
+ .modemuxs = pci_modemux,
+ .nmodemuxs = ARRAY_SIZE(pci_modemux),
+};
+
+static const char *const pci_grps[] = { "pci_grp" };
+static struct spear_function pci_function = {
+ .name = "pci",
+ .groups = pci_grps,
+ .ngroups = ARRAY_SIZE(pci_grps),
+};
+
+/* pad multiplexing for (fix-part) pcie0 device */
static struct spear_muxreg pcie0_muxreg[] = {
- PCI_SATA_MUXREG,
{
.reg = PCIE_SATA_CFG,
.mask = PCIE_CFG_VAL(0),
@@ -1802,15 +2071,12 @@ static struct spear_modemux pcie0_modemux[] = {
static struct spear_pingroup pcie0_pingroup = {
.name = "pcie0_grp",
- .pins = pci_sata_pins,
- .npins = ARRAY_SIZE(pci_sata_pins),
.modemuxs = pcie0_modemux,
.nmodemuxs = ARRAY_SIZE(pcie0_modemux),
};
-/* pad multiplexing for pcie1 device */
+/* pad multiplexing for (fix-part) pcie1 device */
static struct spear_muxreg pcie1_muxreg[] = {
- PCI_SATA_MUXREG,
{
.reg = PCIE_SATA_CFG,
.mask = PCIE_CFG_VAL(1),
@@ -1827,15 +2093,12 @@ static struct spear_modemux pcie1_modemux[] = {
static struct spear_pingroup pcie1_pingroup = {
.name = "pcie1_grp",
- .pins = pci_sata_pins,
- .npins = ARRAY_SIZE(pci_sata_pins),
.modemuxs = pcie1_modemux,
.nmodemuxs = ARRAY_SIZE(pcie1_modemux),
};
-/* pad multiplexing for pcie2 device */
+/* pad multiplexing for (fix-part) pcie2 device */
static struct spear_muxreg pcie2_muxreg[] = {
- PCI_SATA_MUXREG,
{
.reg = PCIE_SATA_CFG,
.mask = PCIE_CFG_VAL(2),
@@ -1852,22 +2115,20 @@ static struct spear_modemux pcie2_modemux[] = {
static struct spear_pingroup pcie2_pingroup = {
.name = "pcie2_grp",
- .pins = pci_sata_pins,
- .npins = ARRAY_SIZE(pci_sata_pins),
.modemuxs = pcie2_modemux,
.nmodemuxs = ARRAY_SIZE(pcie2_modemux),
};
-static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" };
-static struct spear_function pci_function = {
- .name = "pci",
- .groups = pci_grps,
- .ngroups = ARRAY_SIZE(pci_grps),
+static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp"
+};
+static struct spear_function pcie_function = {
+ .name = "pci_express",
+ .groups = pcie_grps,
+ .ngroups = ARRAY_SIZE(pcie_grps),
};
/* pad multiplexing for sata0 device */
static struct spear_muxreg sata0_muxreg[] = {
- PCI_SATA_MUXREG,
{
.reg = PCIE_SATA_CFG,
.mask = SATA_CFG_VAL(0),
@@ -1884,15 +2145,12 @@ static struct spear_modemux sata0_modemux[] = {
static struct spear_pingroup sata0_pingroup = {
.name = "sata0_grp",
- .pins = pci_sata_pins,
- .npins = ARRAY_SIZE(pci_sata_pins),
.modemuxs = sata0_modemux,
.nmodemuxs = ARRAY_SIZE(sata0_modemux),
};
/* pad multiplexing for sata1 device */
static struct spear_muxreg sata1_muxreg[] = {
- PCI_SATA_MUXREG,
{
.reg = PCIE_SATA_CFG,
.mask = SATA_CFG_VAL(1),
@@ -1909,15 +2167,12 @@ static struct spear_modemux sata1_modemux[] = {
static struct spear_pingroup sata1_pingroup = {
.name = "sata1_grp",
- .pins = pci_sata_pins,
- .npins = ARRAY_SIZE(pci_sata_pins),
.modemuxs = sata1_modemux,
.nmodemuxs = ARRAY_SIZE(sata1_modemux),
};
/* pad multiplexing for sata2 device */
static struct spear_muxreg sata2_muxreg[] = {
- PCI_SATA_MUXREG,
{
.reg = PCIE_SATA_CFG,
.mask = SATA_CFG_VAL(2),
@@ -1934,8 +2189,6 @@ static struct spear_modemux sata2_modemux[] = {
static struct spear_pingroup sata2_pingroup = {
.name = "sata2_grp",
- .pins = pci_sata_pins,
- .npins = ARRAY_SIZE(pci_sata_pins),
.modemuxs = sata2_modemux,
.nmodemuxs = ARRAY_SIZE(sata2_modemux),
};
@@ -1957,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = {
PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
PMX_NFCE2_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_1,
+ .mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+ PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+ PMX_NFCE2_MASK,
+ .val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+ PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+ PMX_NFCE2_MASK,
},
};
@@ -1983,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = {
.mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+ PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
+ .val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+ PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
},
};
@@ -2017,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = {
.mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
| PMX_MCILEDS_MASK,
.val = 0,
+ }, {
+ .reg = PAD_DIRECTION_SEL_2,
+ .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+ | PMX_MCILEDS_MASK,
+ .val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+ | PMX_MCILEDS_MASK,
},
};
@@ -2093,6 +2366,7 @@ static struct spear_pingroup *spear1310_pingroups[] = {
&can0_dis_sd_pingroup,
&can1_dis_sd_pingroup,
&can1_dis_kbd_pingroup,
+ &pci_pingroup,
&pcie0_pingroup,
&pcie1_pingroup,
&pcie2_pingroup,
@@ -2138,6 +2412,7 @@ static struct spear_function *spear1310_functions[] = {
&can0_function,
&can1_function,
&pci_function,
+ &pcie_function,
&sata_function,
&ssp1_function,
&gpt64_function,
diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
index a0eb057e55b..0606b8cf3f2 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
@@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = {
* Pad multiplexing for making all pads as gpio's. This is done to override the
* values passed from bootloader and start from scratch.
*/
-static const unsigned pads_as_gpio_pins[] = { 251 };
+static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 };
static struct spear_muxreg pads_as_gpio_muxreg[] = {
{
.reg = PAD_FUNCTION_EN_1,
@@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = {
.nmodemuxs = ARRAY_SIZE(clcd_modemux),
};
-static const char *const clcd_grps[] = { "clcd_grp" };
+/* Disable cld runtime to save panel damage */
+static struct spear_muxreg clcd_sleep_muxreg[] = {
+ {
+ .reg = PAD_SHARED_IP_EN_1,
+ .mask = ARM_TRACE_MASK | MIPHY_DBG_MASK,
+ .val = 0,
+ }, {
+ .reg = PAD_FUNCTION_EN_5,
+ .mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK,
+ .val = 0x0,
+ }, {
+ .reg = PAD_FUNCTION_EN_6,
+ .mask = CLCD_AND_ARM_TRACE_REG5_MASK,
+ .val = 0x0,
+ }, {
+ .reg = PAD_FUNCTION_EN_7,
+ .mask = CLCD_AND_ARM_TRACE_REG6_MASK,
+ .val = 0x0,
+ },
+};
+
+static struct spear_modemux clcd_sleep_modemux[] = {
+ {
+ .muxregs = clcd_sleep_muxreg,
+ .nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg),
+ },
+};
+
+static struct spear_pingroup clcd_sleep_pingroup = {
+ .name = "clcd_sleep_grp",
+ .pins = clcd_pins,
+ .npins = ARRAY_SIZE(clcd_pins),
+ .modemuxs = clcd_sleep_modemux,
+ .nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux),
+};
+
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" };
static struct spear_function clcd_function = {
.name = "clcd",
.groups = clcd_grps,
@@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = {
&sdhci_pingroup,
&cf_pingroup,
&xd_pingroup,
+ &clcd_sleep_pingroup,
&clcd_pingroup,
&arm_trace_pingroup,
&miphy_dbg_pingroup,
diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
index 020b1e0bdb3..ca47b0e5078 100644
--- a/drivers/pinctrl/spear/pinctrl-spear320.c
+++ b/drivers/pinctrl/spear/pinctrl-spear320.c
@@ -2240,6 +2240,10 @@ static struct spear_muxreg pwm2_pin_34_muxreg[] = {
.mask = PMX_SSP_CS_MASK,
.val = 0,
}, {
+ .reg = MODE_CONFIG_REG,
+ .mask = PMX_PWM_MASK,
+ .val = PMX_PWM_MASK,
+ }, {
.reg = IP_SEL_PAD_30_39_REG,
.mask = PMX_PL_34_MASK,
.val = PMX_PWM2_PL_34_VAL,
@@ -2956,9 +2960,9 @@ static struct spear_function mii2_function = {
};
/* Pad multiplexing for cadence mii 1_2 as smii or rmii device */
-static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
+static const unsigned rmii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27 };
-static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
+static const unsigned smii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
static struct spear_muxreg mii0_1_muxreg[] = {
{
.reg = PMX_CONFIG_REG,
diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.h b/drivers/pinctrl/spear/pinctrl-spear3xx.h
index 31f44347f17..7860b36053c 100644
--- a/drivers/pinctrl/spear/pinctrl-spear3xx.h
+++ b/drivers/pinctrl/spear/pinctrl-spear3xx.h
@@ -15,6 +15,7 @@
#include "pinctrl-spear.h"
/* pad mux declarations */
+#define PMX_PWM_MASK (1 << 16)
#define PMX_FIRDA_MASK (1 << 14)
#define PMX_I2C_MASK (1 << 13)
#define PMX_SSP_CS_MASK (1 << 12)
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 49a89397231..b1d956d81f0 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -335,6 +335,9 @@ config AB8500_BATTERY_THERM_ON_BATCTRL
help
Say Y to enable battery temperature measurements using
thermistor connected on BATCTRL ADC.
+
+source "drivers/power/reset/Kconfig"
+
endif # POWER_SUPPLY
source "drivers/power/avs/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b949cf85590..f1d99f4a0bc 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
obj-$(CONFIG_POWER_AVS) += avs/
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
+obj-$(CONFIG_POWER_RESET) += reset/
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
new file mode 100644
index 00000000000..6461b489fb0
--- /dev/null
+++ b/drivers/power/reset/Kconfig
@@ -0,0 +1,15 @@
+menuconfig POWER_RESET
+ bool "Board level reset or power off"
+ help
+ Provides a number of drivers which either reset a complete board
+ or shut it down, by manipulating the main power supply on the board.
+
+ Say Y here to enable board reset and power off
+
+config POWER_RESET_GPIO
+ bool "GPIO power-off driver"
+ depends on OF_GPIO && POWER_RESET
+ help
+ This driver supports turning off your board via a GPIO line.
+ If your board needs a GPIO high/low to power down, say Y and
+ create a binding in your devicetree.
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
new file mode 100644
index 00000000000..751488a4a0c
--- /dev/null
+++ b/drivers/power/reset/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
new file mode 100644
index 00000000000..0491e5335d0
--- /dev/null
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -0,0 +1,129 @@
+/*
+ * Toggles a GPIO pin to power down a device
+ *
+ * Jamie Lentin <jm@lentin.co.uk>
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Copyright (C) 2012 Jamie Lentin
+ *
+ * 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.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/module.h>
+
+/*
+ * Hold configuration here, cannot be more than one instance of the driver
+ * since pm_power_off itself is global.
+ */
+static int gpio_num = -1;
+static int gpio_active_low;
+
+static void gpio_poweroff_do_poweroff(void)
+{
+ BUG_ON(gpio_num == -1);
+
+ /* drive it active */
+ gpio_direction_output(gpio_num, !gpio_active_low);
+ mdelay(100);
+ /* rising edge or drive inactive */
+ gpio_set_value(gpio_num, gpio_active_low);
+ mdelay(100);
+ /* falling edge */
+ gpio_set_value(gpio_num, !gpio_active_low);
+
+ /* give it some time */
+ mdelay(3000);
+
+ WARN_ON(1);
+}
+
+static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
+{
+ enum of_gpio_flags flags;
+ bool input = false;
+ int ret;
+
+ /* If a pm_power_off function has already been added, leave it alone */
+ if (pm_power_off != NULL) {
+ pr_err("%s: pm_power_off function already registered",
+ __func__);
+ return -EBUSY;
+ }
+
+ gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
+ if (gpio_num < 0) {
+ pr_err("%s: Could not get GPIO configuration: %d",
+ __func__, gpio_num);
+ return -ENODEV;
+ }
+ gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+ if (of_get_property(pdev->dev.of_node, "input", NULL))
+ input = true;
+
+ ret = gpio_request(gpio_num, "poweroff-gpio");
+ if (ret) {
+ pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
+ return ret;
+ }
+ if (input) {
+ if (gpio_direction_input(gpio_num)) {
+ pr_err("Could not set direction of GPIO %d to input",
+ gpio_num);
+ goto err;
+ }
+ } else {
+ if (gpio_direction_output(gpio_num, gpio_active_low)) {
+ pr_err("Could not set direction of GPIO %d", gpio_num);
+ goto err;
+ }
+ }
+
+ pm_power_off = &gpio_poweroff_do_poweroff;
+ return 0;
+
+err:
+ gpio_free(gpio_num);
+ return -ENODEV;
+}
+
+static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
+{
+ if (gpio_num != -1)
+ gpio_free(gpio_num);
+ if (pm_power_off == &gpio_poweroff_do_poweroff)
+ pm_power_off = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id of_gpio_poweroff_match[] = {
+ { .compatible = "gpio-poweroff", },
+ {},
+};
+
+static struct platform_driver gpio_poweroff_driver = {
+ .probe = gpio_poweroff_probe,
+ .remove = __devexit_p(gpio_poweroff_remove),
+ .driver = {
+ .name = "poweroff-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_gpio_poweroff_match,
+ },
+};
+
+module_platform_driver(gpio_poweroff_driver);
+
+MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
+MODULE_DESCRIPTION("GPIO poweroff driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:poweroff-gpio");
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index c17ae22567e..0c6fcb461fa 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
/**
* rio_map_inb_region -- Map inbound memory region.
* @mport: Master port.
- * @lstart: physical address of memory region to be mapped
+ * @local: physical address of memory region to be mapped
* @rbase: RIO base address assigned to this window
* @size: Size of the memory region
* @rflags: Flags for mapping.
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 5c4829cba6a..e872c8be080 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
}
EXPORT_SYMBOL_GPL(regulator_get_exclusive);
-/**
- * regulator_put - "free" the regulator source
- * @regulator: regulator source
- *
- * Note: drivers must ensure that all regulator_enable calls made on this
- * regulator source are balanced by regulator_disable calls prior to calling
- * this function.
- */
-void regulator_put(struct regulator *regulator)
+/* Locks held by regulator_put() */
+static void _regulator_put(struct regulator *regulator)
{
struct regulator_dev *rdev;
if (regulator == NULL || IS_ERR(regulator))
return;
- mutex_lock(&regulator_list_mutex);
rdev = regulator->rdev;
debugfs_remove_recursive(regulator->debugfs);
@@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator)
rdev->exclusive = 0;
module_put(rdev->owner);
+}
+
+/**
+ * regulator_put - "free" the regulator source
+ * @regulator: regulator source
+ *
+ * Note: drivers must ensure that all regulator_enable calls made on this
+ * regulator source are balanced by regulator_disable calls prior to calling
+ * this function.
+ */
+void regulator_put(struct regulator *regulator)
+{
+ mutex_lock(&regulator_list_mutex);
+ _regulator_put(regulator);
mutex_unlock(&regulator_list_mutex);
}
EXPORT_SYMBOL_GPL(regulator_put);
@@ -1974,7 +1980,7 @@ int regulator_is_supported_voltage(struct regulator *regulator,
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
ret = regulator_get_voltage(regulator);
if (ret >= 0)
- return (min_uV >= ret && ret <= max_uV);
+ return (min_uV <= ret && ret <= max_uV);
else
return ret;
}
@@ -3365,7 +3371,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
if (ret != 0) {
rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
config->ena_gpio, ret);
- goto clean;
+ goto wash;
}
rdev->ena_gpio = config->ena_gpio;
@@ -3445,10 +3451,11 @@ unset_supplies:
scrub:
if (rdev->supply)
- regulator_put(rdev->supply);
+ _regulator_put(rdev->supply);
if (rdev->ena_gpio)
gpio_free(rdev->ena_gpio);
kfree(rdev->constraints);
+wash:
device_unregister(&rdev->dev);
/* device core frees rdev */
rdev = ERR_PTR(ret);
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index cd0106293a4..7304139934a 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -17,8 +17,6 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
-#include <mach/hardware.h>
-
#define RTC_INPUT_CLK_32768HZ (0x00 << 5)
#define RTC_INPUT_CLK_32000HZ (0x01 << 5)
#define RTC_INPUT_CLK_38400HZ (0x02 << 5)
@@ -72,14 +70,38 @@ static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = {
#define RTC_TEST2 0x2C /* 32bit rtc test reg 2 */
#define RTC_TEST3 0x30 /* 32bit rtc test reg 3 */
+enum imx_rtc_type {
+ IMX1_RTC,
+ IMX21_RTC,
+};
+
struct rtc_plat_data {
struct rtc_device *rtc;
void __iomem *ioaddr;
int irq;
struct clk *clk;
struct rtc_time g_rtc_alarm;
+ enum imx_rtc_type devtype;
};
+static struct platform_device_id imx_rtc_devtype[] = {
+ {
+ .name = "imx1-rtc",
+ .driver_data = IMX1_RTC,
+ }, {
+ .name = "imx21-rtc",
+ .driver_data = IMX21_RTC,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imx_rtc_devtype);
+
+static inline int is_imx1_rtc(struct rtc_plat_data *data)
+{
+ return data->devtype == IMX1_RTC;
+}
+
/*
* This function is used to obtain the RTC time or the alarm value in
* second.
@@ -278,10 +300,13 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
*/
static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
/*
* TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only
*/
- if (cpu_is_mx1()) {
+ if (is_imx1_rtc(pdata)) {
struct rtc_time tm;
rtc_time_to_tm(time, &tm);
@@ -360,6 +385,8 @@ static int __devinit mxc_rtc_probe(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;
+ pdata->devtype = pdev->id_entry->driver_data;
+
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), pdev->name))
return -EBUSY;
@@ -480,6 +507,7 @@ static struct platform_driver mxc_rtc_driver = {
#endif
.owner = THIS_MODULE,
},
+ .id_table = imx_rtc_devtype,
.probe = mxc_rtc_probe,
.remove = __devexit_p(mxc_rtc_remove),
};
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 9ffb6d5f17a..4ed343e4eb4 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -44,7 +44,6 @@
#define RAW3215_NR_CCWS 3
#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */
-#define RAW3215_FIXED 1 /* 3215 console device is not be freed */
#define RAW3215_WORKING 4 /* set if a request is being worked on */
#define RAW3215_THROTTLED 8 /* set if reading is disabled */
#define RAW3215_STOPPED 16 /* set if writing is disabled */
@@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data)
struct tty_struct *tty;
tty = tty_port_tty_get(&raw->port);
- tty_wakeup(tty);
- tty_kref_put(tty);
+ if (tty) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
+ }
}
/*
@@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw)
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
- if (!(raw->port.flags & ASYNC_INITIALIZED) ||
- (raw->flags & RAW3215_FIXED))
+ if (!(raw->port.flags & ASYNC_INITIALIZED))
return;
/* Wait for outstanding requests, then free irq */
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -926,8 +926,6 @@ static int __init con3215_init(void)
dev_set_drvdata(&cdev->dev, raw);
cdev->handler = raw3215_irq;
- raw->flags |= RAW3215_FIXED;
-
/* Request the console irq */
if (raw3215_startup(raw) != 0) {
raw3215_free_info(raw);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 33bb4d891e1..4af3dfe70ef 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
extern void css_reiterate_subchannels(void);
void css_update_ssd_info(struct subchannel *sch);
-#define __MAX_SUBCHANNEL 65535
-#define __MAX_SSID 3
-
struct channel_subsystem {
u8 cssid;
int valid;
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index fc916f5d731..fd3143c291c 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
}
if (device_is_disconnected(cdev))
return IO_SCH_REPROBE;
- if (cdev->online)
+ if (cdev->online && !cdev->private->flags.resuming)
return IO_SCH_VERIFY;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return IO_SCH_UNREG_ATTACH;
@@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
rc = 0;
goto out_unlock;
case IO_SCH_VERIFY:
- if (cdev->private->flags.resuming == 1) {
- if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) {
- ccw_device_set_notoper(cdev);
- break;
- }
- }
/* Trigger path verification. */
io_subchannel_verify(sch);
rc = 0;
diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c
index 199bc679117..65d13e38803 100644
--- a/drivers/s390/cio/idset.c
+++ b/drivers/s390/cio/idset.c
@@ -125,8 +125,7 @@ int idset_is_empty(struct idset *set)
void idset_add_set(struct idset *to, struct idset *from)
{
- int len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
- __BITOPS_WORDS(from->num_ssid * from->num_id));
+ int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id);
bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);
}
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 3e25d315045..4d6ba00d004 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -2942,13 +2942,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
QETH_DBF_TEXT(SETUP, 2, "qipasscb");
cmd = (struct qeth_ipa_cmd *) data;
+
+ switch (cmd->hdr.return_code) {
+ case IPA_RC_NOTSUPP:
+ case IPA_RC_L2_UNSUPPORTED_CMD:
+ QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
+ card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
+ card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
+ return -0;
+ default:
+ if (cmd->hdr.return_code) {
+ QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled "
+ "rc=%d\n",
+ dev_name(&card->gdev->dev),
+ cmd->hdr.return_code);
+ return 0;
+ }
+ }
+
if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
- } else {
+ } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) {
card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
- }
+ } else
+ QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
+ "\n", dev_name(&card->gdev->dev));
QETH_DBF_TEXT(SETUP, 2, "suppenbl");
QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index e67e0258aec..fddb62654b6 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
QETH_DBF_TEXT(SETUP, 2, "doL2init");
QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
- rc = qeth_query_setadapterparms(card);
- if (rc) {
- QETH_DBF_MESSAGE(2, "could not query adapter parameters on "
- "device %s: x%x\n", CARD_BUS_ID(card), rc);
+ if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
+ rc = qeth_query_setadapterparms(card);
+ if (rc) {
+ QETH_DBF_MESSAGE(2, "could not query adapter "
+ "parameters on device %s: x%x\n",
+ CARD_BUS_ID(card), rc);
+ }
}
if (card->info.type == QETH_CARD_TYPE_IQD ||
@@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
return -ERESTARTSYS;
}
rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
- if (!rc)
+ if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND))
rc = qeth_l2_send_setmac(card, addr->sa_data);
return rc ? -EINVAL : 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index bd4708a422c..20fd974f903 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
int
qla24xx_disable_vp(scsi_qla_host_t *vha)
{
+ unsigned long flags;
int ret;
ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
@@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
/* Remove port id from vp target map */
+ spin_lock_irqsave(&vha->hw->vport_slock, flags);
qlt_update_vp_map(vha, RESET_AL_PA);
+ spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
qla2x00_mark_vp_devices_dead(vha);
atomic_set(&vha->vp_state, VP_FAILED);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 0e09d8f433d..62aa5584f64 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
int pmap_len;
fc_port_t *fcport;
int global_resets;
+ unsigned long flags;
retry:
global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
@@ -625,10 +626,10 @@ retry:
sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
- sess->s_id = fcport->d_id;
- sess->loop_id = fcport->loop_id;
- sess->conf_compl_supported = !!(fcport->flags &
- FCF_CONF_COMP_SUPPORTED);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+ (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
res = true;
@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(
qlt_undelete_sess(sess);
kref_get(&sess->se_sess->sess_kref);
- sess->s_id = fcport->d_id;
- sess->loop_id = fcport->loop_id;
- sess->conf_compl_supported = !!(fcport->flags &
- FCF_CONF_COMP_SUPPORTED);
+ ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+ (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+
if (sess->local && !local)
sess->local = 0;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(
*/
kref_get(&sess->se_sess->sess_kref);
- sess->conf_compl_supported = !!(fcport->flags &
- FCF_CONF_COMP_SUPPORTED);
+ sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
"Reappeared sess %p\n", sess);
}
- sess->s_id = fcport->d_id;
- sess->loop_id = fcport->loop_id;
- sess->conf_compl_supported = !!(fcport->flags &
- FCF_CONF_COMP_SUPPORTED);
+ ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+ (fcport->flags & FCF_CONF_COMP_SUPPORTED));
}
if (sess && sess->local) {
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 170af157121..bad749561ec 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {
int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
void *, uint8_t *, uint16_t);
+ void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
const uint16_t);
struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 2358c16c4c8..3d74f2f39ae 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
struct tcm_qla2xxx_tpg, se_tpg);
struct tcm_qla2xxx_lport *lport = tpg->lport;
- return &lport->lport_name[0];
+ return lport->lport_naa_name;
}
static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
@@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(
return 0;
}
+static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
+ uint16_t loop_id, bool conf_compl_supported)
+{
+ struct qla_tgt *tgt = sess->tgt;
+ struct qla_hw_data *ha = tgt->ha;
+ struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr;
+ struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
+ struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
+ struct tcm_qla2xxx_nacl, se_node_acl);
+ u32 key;
+
+
+ if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
+ pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
+ sess,
+ sess->port_name[0], sess->port_name[1],
+ sess->port_name[2], sess->port_name[3],
+ sess->port_name[4], sess->port_name[5],
+ sess->port_name[6], sess->port_name[7],
+ sess->loop_id, loop_id,
+ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+ s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+
+ if (sess->loop_id != loop_id) {
+ /*
+ * Because we can shuffle loop IDs around and we
+ * update different sessions non-atomically, we might
+ * have overwritten this session's old loop ID
+ * already, and we might end up overwriting some other
+ * session that will be updated later. So we have to
+ * be extra careful and we can't warn about those things...
+ */
+ if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl)
+ lport->lport_loopid_map[sess->loop_id].se_nacl = NULL;
+
+ lport->lport_loopid_map[loop_id].se_nacl = se_nacl;
+
+ sess->loop_id = loop_id;
+ }
+
+ if (sess->s_id.b24 != s_id.b24) {
+ key = (((u32) sess->s_id.b.domain << 16) |
+ ((u32) sess->s_id.b.area << 8) |
+ ((u32) sess->s_id.b.al_pa));
+
+ if (btree_lookup32(&lport->lport_fcport_map, key))
+ WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
+ "Found wrong se_nacl when updating s_id %x:%x:%x\n",
+ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+ else
+ WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
+ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+
+ key = (((u32) s_id.b.domain << 16) |
+ ((u32) s_id.b.area << 8) |
+ ((u32) s_id.b.al_pa));
+
+ if (btree_lookup32(&lport->lport_fcport_map, key)) {
+ WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n",
+ s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+ btree_update32(&lport->lport_fcport_map, key, se_nacl);
+ } else {
+ btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
+ }
+
+ sess->s_id = s_id;
+ nacl->nport_id = key;
+ }
+
+ sess->conf_compl_supported = conf_compl_supported;
+}
+
/*
* Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
*/
@@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd,
.free_session = tcm_qla2xxx_free_session,
+ .update_sess = tcm_qla2xxx_update_sess,
.check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
.find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id,
.find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id,
@@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(
lport->lport_wwpn = wwpn;
tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,
wwpn);
+ sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);
ret = tcm_qla2xxx_init_lport(lport);
if (ret != 0)
@@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
lport->lport_npiv_wwnn = npiv_wwnn;
tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
+ sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
/* FIXME: tcm_qla2xxx_npiv_make_lport */
ret = -ENOSYS;
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
index 82549810335..9ba075fe978 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
@@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {
u64 lport_npiv_wwnn;
/* ASCII formatted WWPN for FC Target Lport */
char lport_name[TCM_QLA2XXX_NAMELEN];
+ /* ASCII formatted naa WWPN for VPD page 83 etc */
+ char lport_naa_name[TCM_QLA2XXX_NAMELEN];
/* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
/* map for fc_port pointers in 24-bit FC Port ID space */
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index b191dd54920..71fddbc60f1 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1294,26 +1294,19 @@ static struct scsi_host_template qpti_template = {
static const struct of_device_id qpti_match[];
static int __devinit qpti_sbus_probe(struct platform_device *op)
{
- const struct of_device_id *match;
- struct scsi_host_template *tpnt;
struct device_node *dp = op->dev.of_node;
struct Scsi_Host *host;
struct qlogicpti *qpti;
static int nqptis;
const char *fcode;
- match = of_match_device(qpti_match, &op->dev);
- if (!match)
- return -EINVAL;
- tpnt = match->data;
-
/* Sometimes Antares cards come up not completely
* setup, and we get a report of a zero IRQ.
*/
if (op->archdata.irqs[0] == 0)
return -ENODEV;
- host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti));
+ host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti));
if (!host)
return -ENOMEM;
@@ -1445,19 +1438,15 @@ static int __devexit qpti_sbus_remove(struct platform_device *op)
static const struct of_device_id qpti_match[] = {
{
.name = "ptisp",
- .data = &qpti_template,
},
{
.name = "PTI,ptisp",
- .data = &qpti_template,
},
{
.name = "QLGC,isp",
- .data = &qpti_template,
},
{
.name = "SUNW,isp",
- .data = &qpti_template,
},
{},
};
diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h
index f2ffd963f1c..d0cafd63719 100644
--- a/drivers/staging/android/android_alarm.h
+++ b/drivers/staging/android/android_alarm.h
@@ -51,12 +51,10 @@ enum android_alarm_return_flags {
#define ANDROID_ALARM_WAIT _IO('a', 1)
#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size)
-#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size)
-
/* Set alarm */
#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec)
#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec)
#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec)
#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0)))
#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4)
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 094fdc366f3..97cdf0856ae 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -39,7 +39,6 @@
#include <linux/workqueue.h>
#include <mach/clk.h>
-#include <mach/iomap.h>
#include "nvec.h"
diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
index 5e2f4d82d92..7f3a1db3161 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
@@ -40,7 +40,6 @@
#include <linux/vmalloc.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
-#include <plat/clock.h>
#include <linux/clk.h>
#include <plat/mailbox.h>
#include <linux/pagemap.h>
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index d6ce2182e67..035c2c76253 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3719,7 +3719,9 @@ restart:
*/
iscsit_thread_check_cpumask(conn, current, 1);
- schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+ wait_event_interruptible(conn->queues_wq,
+ !iscsit_conn_all_queues_empty(conn) ||
+ ts->status == ISCSI_THREAD_SET_RESET);
if ((ts->status == ISCSI_THREAD_SET_RESET) ||
signal_pending(current))
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index 2ba9f9b9435..21048dbf7d1 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -486,6 +486,7 @@ struct iscsi_tmr_req {
};
struct iscsi_conn {
+ wait_queue_head_t queues_wq;
/* Authentication Successful for this connection */
u8 auth_complete;
/* State connection is currently in */
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index cdc8a10939c..f8dbec05d5e 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -41,6 +41,7 @@
static int iscsi_login_init_conn(struct iscsi_conn *conn)
{
+ init_waitqueue_head(&conn->queues_wq);
INIT_LIST_HEAD(&conn->conn_list);
INIT_LIST_HEAD(&conn->conn_cmd_list);
INIT_LIST_HEAD(&conn->immed_queue_list);
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index afd98ccd40a..1a91195ab61 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(
atomic_set(&conn->check_immediate_queue, 1);
spin_unlock_bh(&conn->immed_queue_lock);
- wake_up_process(conn->thread_set->tx_thread);
+ wake_up(&conn->queues_wq);
}
struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
@@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(
atomic_inc(&cmd->response_queue_count);
spin_unlock_bh(&conn->response_queue_lock);
- wake_up_process(conn->thread_set->tx_thread);
+ wake_up(&conn->queues_wq);
}
struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
@@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(
}
}
+bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn)
+{
+ bool empty;
+
+ spin_lock_bh(&conn->immed_queue_lock);
+ empty = list_empty(&conn->immed_queue_list);
+ spin_unlock_bh(&conn->immed_queue_lock);
+
+ if (!empty)
+ return empty;
+
+ spin_lock_bh(&conn->response_queue_lock);
+ empty = list_empty(&conn->response_queue_list);
+ spin_unlock_bh(&conn->response_queue_lock);
+
+ return empty;
+}
+
void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
{
struct iscsi_queue_req *qr, *qr_tmp;
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
index 44054bd3543..894d0f83792 100644
--- a/drivers/target/iscsi/iscsi_target_util.h
+++ b/drivers/target/iscsi/iscsi_target_util.h
@@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_
extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
+extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
extern void iscsit_release_cmd(struct iscsi_cmd *);
extern void iscsit_free_cmd(struct iscsi_cmd *);
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 015f5be27bf..c123327499a 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)
if (ret < 0)
goto out;
- if (core_dev_setup_virtual_lun0() < 0)
+ ret = core_dev_setup_virtual_lun0();
+ if (ret < 0)
goto out;
return 0;
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 8d774da1632..9abef9f8eb7 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)
static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
{
- u32 tmp, aligned_max_sectors;
+ u32 aligned_max_sectors;
+ u32 alignment;
/*
* Limit max_sectors to a PAGE_SIZE aligned value for modern
* transport_allocate_data_tasks() operation.
*/
- tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
- aligned_max_sectors = (tmp / block_size);
- if (max_sectors != aligned_max_sectors) {
- printk(KERN_INFO "Rounding down aligned max_sectors from %u"
- " to %u\n", max_sectors, aligned_max_sectors);
- return aligned_max_sectors;
- }
+ alignment = max(1ul, PAGE_SIZE / block_size);
+ aligned_max_sectors = rounddown(max_sectors, alignment);
+
+ if (max_sectors != aligned_max_sectors)
+ pr_info("Rounding down aligned max_sectors from %u to %u\n",
+ max_sectors, aligned_max_sectors);
- return max_sectors;
+ return aligned_max_sectors;
}
void se_dev_set_default_attribs(
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 868f8aa04f1..a6e27d967c7 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)
return 0;
}
+static int sbc_emulate_noop(struct se_cmd *cmd)
+{
+ target_complete_cmd(cmd, GOOD);
+ return 0;
+}
+
static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
{
return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
@@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
size = 0;
cmd->execute_cmd = sbc_emulate_verify;
break;
+ case REZERO_UNIT:
+ case SEEK_6:
+ case SEEK_10:
+ /*
+ * There are still clients out there which use these old SCSI-2
+ * commands. This mainly happens when running VMs with legacy
+ * guest systems, connected via SCSI command pass-through to
+ * iSCSI targets. Make them happy and return status GOOD.
+ */
+ size = 0;
+ cmd->execute_cmd = sbc_emulate_noop;
+ break;
default:
ret = spc_parse_cdb(cmd, &size);
if (ret)
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 9229bd9ad61..6fd434d3d7e 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
unsigned char buf[SE_INQUIRY_BUF];
int p, ret;
+ memset(buf, 0, SE_INQUIRY_BUF);
+
if (dev == tpg->tpg_virt_lun0.lun_se_dev)
buf[0] = 0x3f; /* Not connected */
else
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 1c59a3c23b2..be75c4331a9 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -140,15 +140,15 @@ void core_tmr_abort_task(
printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
se_cmd->se_tfo->get_fabric_name(), ref_tag);
- spin_lock_irq(&se_cmd->t_state_lock);
+ spin_lock(&se_cmd->t_state_lock);
if (se_cmd->transport_state & CMD_T_COMPLETE) {
printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
- spin_unlock_irq(&se_cmd->t_state_lock);
+ spin_unlock(&se_cmd->t_state_lock);
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
goto out;
}
se_cmd->transport_state |= CMD_T_ABORTED;
- spin_unlock_irq(&se_cmd->t_state_lock);
+ spin_unlock(&se_cmd->t_state_lock);
list_del_init(&se_cmd->se_cmd_list);
kref_get(&se_cmd->cmd_kref);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index c33baff86aa..9097155e9eb 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)
se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
se_cmd->se_tfo->queue_tm_rsp(se_cmd);
- transport_generic_free_cmd(se_cmd, 0);
}
/**
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
index fd03e8581af..6dd29e4ce36 100644
--- a/drivers/thermal/exynos_thermal.c
+++ b/drivers/thermal/exynos_thermal.c
@@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
},
{ },
};
-MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids);
+MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
struct platform_device *pdev)
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index d4452716aaa..f7a1b574a30 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
goto error_free_priv;
}
- zone = thermal_zone_device_register("rcar_thermal", 0, priv,
+ zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
&rcar_thermal_zone_ops, 0, 0);
if (IS_ERR(zone)) {
dev_err(&pdev->dev, "thermal zone device is NULL\n");
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index a5dec1ca1b8..13ee53bd0bf 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -424,7 +424,6 @@ static void hvc_hangup(struct tty_struct *tty)
{
struct hvc_struct *hp = tty->driver_data;
unsigned long flags;
- int temp_open_count;
if (!hp)
return;
@@ -444,7 +443,6 @@ static void hvc_hangup(struct tty_struct *tty)
return;
}
- temp_open_count = hp->port.count;
hp->port.count = 0;
spin_unlock_irqrestore(&hp->port.lock, flags);
tty_port_tty_set(&hp->port, NULL);
@@ -453,11 +451,6 @@ static void hvc_hangup(struct tty_struct *tty)
if (hp->ops->notifier_hangup)
hp->ops->notifier_hangup(hp, hp->data);
-
- while(temp_open_count) {
- --temp_open_count;
- tty_port_put(&hp->port);
- }
}
/*
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 8c0b7b42319..60b076cc4e2 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -73,10 +73,42 @@
#define ECHO_OP_SET_CANON_COL 0x81
#define ECHO_OP_ERASE_TAB 0x82
+struct n_tty_data {
+ unsigned int column;
+ unsigned long overrun_time;
+ int num_overrun;
+
+ unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
+ unsigned char echo_overrun:1;
+
+ DECLARE_BITMAP(process_char_map, 256);
+ DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE);
+
+ char *read_buf;
+ int read_head;
+ int read_tail;
+ int read_cnt;
+
+ unsigned char *echo_buf;
+ unsigned int echo_pos;
+ unsigned int echo_cnt;
+
+ int canon_data;
+ unsigned long canon_head;
+ unsigned int canon_column;
+
+ struct mutex atomic_read_lock;
+ struct mutex output_lock;
+ struct mutex echo_lock;
+ spinlock_t read_lock;
+};
+
static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
unsigned char __user *ptr)
{
- tty_audit_add_data(tty, &x, 1);
+ struct n_tty_data *ldata = tty->disc_data;
+
+ tty_audit_add_data(tty, &x, 1, ldata->icanon);
return put_user(x, ptr);
}
@@ -92,17 +124,18 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
static void n_tty_set_room(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
int left;
int old_left;
- /* tty->read_cnt is not read locked ? */
+ /* ldata->read_cnt is not read locked ? */
if (I_PARMRK(tty)) {
/* Multiply read_cnt by 3, since each byte might take up to
* three times as many spaces when PARMRK is set (depending on
* its flags, e.g. parity error). */
- left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+ left = N_TTY_BUF_SIZE - ldata->read_cnt * 3 - 1;
} else
- left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+ left = N_TTY_BUF_SIZE - ldata->read_cnt - 1;
/*
* If we are doing input canonicalization, and there are no
@@ -111,44 +144,47 @@ static void n_tty_set_room(struct tty_struct *tty)
* characters will be beeped.
*/
if (left <= 0)
- left = tty->icanon && !tty->canon_data;
+ left = ldata->icanon && !ldata->canon_data;
old_left = tty->receive_room;
tty->receive_room = left;
/* Did this open up the receive buffer? We may need to flip */
- if (left && !old_left)
- schedule_work(&tty->buf.work);
+ if (left && !old_left) {
+ WARN_RATELIMIT(tty->port->itty == NULL,
+ "scheduling with invalid itty");
+ schedule_work(&tty->port->buf.work);
+ }
}
-static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata)
{
- if (tty->read_cnt < N_TTY_BUF_SIZE) {
- tty->read_buf[tty->read_head] = c;
- tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt++;
+ if (ldata->read_cnt < N_TTY_BUF_SIZE) {
+ ldata->read_buf[ldata->read_head] = c;
+ ldata->read_head = (ldata->read_head + 1) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt++;
}
}
/**
* put_tty_queue - add character to tty
* @c: character
- * @tty: tty device
+ * @ldata: n_tty data
*
* Add a character to the tty read_buf queue. This is done under the
* read_lock to serialize character addition and also to protect us
* against parallel reads or flushes
*/
-static void put_tty_queue(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
{
unsigned long flags;
/*
* The problem of stomping on the buffers ends here.
* Why didn't anyone see this one coming? --AJK
*/
- spin_lock_irqsave(&tty->read_lock, flags);
- put_tty_queue_nolock(c, tty);
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ put_tty_queue_nolock(c, ldata);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
}
/**
@@ -179,18 +215,19 @@ static void check_unthrottle(struct tty_struct *tty)
static void reset_buffer_flags(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned long flags;
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_head = tty->read_tail = tty->read_cnt = 0;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_head = ldata->read_tail = ldata->read_cnt = 0;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
- mutex_lock(&tty->echo_lock);
- tty->echo_pos = tty->echo_cnt = tty->echo_overrun = 0;
- mutex_unlock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
+ ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0;
+ mutex_unlock(&ldata->echo_lock);
- tty->canon_head = tty->canon_data = tty->erasing = 0;
- memset(&tty->read_flags, 0, sizeof tty->read_flags);
+ ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
+ bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
n_tty_set_room(tty);
}
@@ -235,18 +272,19 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned long flags;
ssize_t n = 0;
- spin_lock_irqsave(&tty->read_lock, flags);
- if (!tty->icanon) {
- n = tty->read_cnt;
- } else if (tty->canon_data) {
- n = (tty->canon_head > tty->read_tail) ?
- tty->canon_head - tty->read_tail :
- tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ if (!ldata->icanon) {
+ n = ldata->read_cnt;
+ } else if (ldata->canon_data) {
+ n = (ldata->canon_head > ldata->read_tail) ?
+ ldata->canon_head - ldata->read_tail :
+ ldata->canon_head + (N_TTY_BUF_SIZE - ldata->read_tail);
}
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
return n;
}
@@ -301,6 +339,7 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
{
+ struct n_tty_data *ldata = tty->disc_data;
int spaces;
if (!space)
@@ -309,48 +348,48 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
switch (c) {
case '\n':
if (O_ONLRET(tty))
- tty->column = 0;
+ ldata->column = 0;
if (O_ONLCR(tty)) {
if (space < 2)
return -1;
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
tty->ops->write(tty, "\r\n", 2);
return 2;
}
- tty->canon_column = tty->column;
+ ldata->canon_column = ldata->column;
break;
case '\r':
- if (O_ONOCR(tty) && tty->column == 0)
+ if (O_ONOCR(tty) && ldata->column == 0)
return 0;
if (O_OCRNL(tty)) {
c = '\n';
if (O_ONLRET(tty))
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
break;
}
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
break;
case '\t':
- spaces = 8 - (tty->column & 7);
+ spaces = 8 - (ldata->column & 7);
if (O_TABDLY(tty) == XTABS) {
if (space < spaces)
return -1;
- tty->column += spaces;
+ ldata->column += spaces;
tty->ops->write(tty, " ", spaces);
return spaces;
}
- tty->column += spaces;
+ ldata->column += spaces;
break;
case '\b':
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
break;
default:
if (!iscntrl(c)) {
if (O_OLCUC(tty))
c = toupper(c);
if (!is_continuation(c, tty))
- tty->column++;
+ ldata->column++;
}
break;
}
@@ -375,14 +414,15 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
static int process_output(unsigned char c, struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
int space, retval;
- mutex_lock(&tty->output_lock);
+ mutex_lock(&ldata->output_lock);
space = tty_write_room(tty);
retval = do_output_char(c, tty, space);
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->output_lock);
if (retval < 0)
return -1;
else
@@ -411,15 +451,16 @@ static int process_output(unsigned char c, struct tty_struct *tty)
static ssize_t process_output_block(struct tty_struct *tty,
const unsigned char *buf, unsigned int nr)
{
+ struct n_tty_data *ldata = tty->disc_data;
int space;
int i;
const unsigned char *cp;
- mutex_lock(&tty->output_lock);
+ mutex_lock(&ldata->output_lock);
space = tty_write_room(tty);
if (!space) {
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->output_lock);
return 0;
}
if (nr > space)
@@ -431,30 +472,30 @@ static ssize_t process_output_block(struct tty_struct *tty,
switch (c) {
case '\n':
if (O_ONLRET(tty))
- tty->column = 0;
+ ldata->column = 0;
if (O_ONLCR(tty))
goto break_out;
- tty->canon_column = tty->column;
+ ldata->canon_column = ldata->column;
break;
case '\r':
- if (O_ONOCR(tty) && tty->column == 0)
+ if (O_ONOCR(tty) && ldata->column == 0)
goto break_out;
if (O_OCRNL(tty))
goto break_out;
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
break;
case '\t':
goto break_out;
case '\b':
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
break;
default:
if (!iscntrl(c)) {
if (O_OLCUC(tty))
goto break_out;
if (!is_continuation(c, tty))
- tty->column++;
+ ldata->column++;
}
break;
}
@@ -462,7 +503,7 @@ static ssize_t process_output_block(struct tty_struct *tty,
break_out:
i = tty->ops->write(tty, buf, i);
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->output_lock);
return i;
}
@@ -494,21 +535,22 @@ break_out:
static void process_echoes(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
int space, nr;
unsigned char c;
unsigned char *cp, *buf_end;
- if (!tty->echo_cnt)
+ if (!ldata->echo_cnt)
return;
- mutex_lock(&tty->output_lock);
- mutex_lock(&tty->echo_lock);
+ mutex_lock(&ldata->output_lock);
+ mutex_lock(&ldata->echo_lock);
space = tty_write_room(tty);
- buf_end = tty->echo_buf + N_TTY_BUF_SIZE;
- cp = tty->echo_buf + tty->echo_pos;
- nr = tty->echo_cnt;
+ buf_end = ldata->echo_buf + N_TTY_BUF_SIZE;
+ cp = ldata->echo_buf + ldata->echo_pos;
+ nr = ldata->echo_cnt;
while (nr > 0) {
c = *cp;
if (c == ECHO_OP_START) {
@@ -545,7 +587,7 @@ static void process_echoes(struct tty_struct *tty)
* Otherwise, tab spacing is normal.
*/
if (!(num_chars & 0x80))
- num_chars += tty->canon_column;
+ num_chars += ldata->canon_column;
num_bs = 8 - (num_chars & 7);
if (num_bs > space) {
@@ -555,22 +597,22 @@ static void process_echoes(struct tty_struct *tty)
space -= num_bs;
while (num_bs--) {
tty_put_char(tty, '\b');
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
}
cp += 3;
nr -= 3;
break;
case ECHO_OP_SET_CANON_COL:
- tty->canon_column = tty->column;
+ ldata->canon_column = ldata->column;
cp += 2;
nr -= 2;
break;
case ECHO_OP_MOVE_BACK_COL:
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
cp += 2;
nr -= 2;
break;
@@ -582,7 +624,7 @@ static void process_echoes(struct tty_struct *tty)
break;
}
tty_put_char(tty, ECHO_OP_START);
- tty->column++;
+ ldata->column++;
space--;
cp += 2;
nr -= 2;
@@ -604,7 +646,7 @@ static void process_echoes(struct tty_struct *tty)
}
tty_put_char(tty, '^');
tty_put_char(tty, op ^ 0100);
- tty->column += 2;
+ ldata->column += 2;
space -= 2;
cp += 2;
nr -= 2;
@@ -635,20 +677,20 @@ static void process_echoes(struct tty_struct *tty)
}
if (nr == 0) {
- tty->echo_pos = 0;
- tty->echo_cnt = 0;
- tty->echo_overrun = 0;
+ ldata->echo_pos = 0;
+ ldata->echo_cnt = 0;
+ ldata->echo_overrun = 0;
} else {
- int num_processed = tty->echo_cnt - nr;
- tty->echo_pos += num_processed;
- tty->echo_pos &= N_TTY_BUF_SIZE - 1;
- tty->echo_cnt = nr;
+ int num_processed = ldata->echo_cnt - nr;
+ ldata->echo_pos += num_processed;
+ ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
+ ldata->echo_cnt = nr;
if (num_processed > 0)
- tty->echo_overrun = 0;
+ ldata->echo_overrun = 0;
}
- mutex_unlock(&tty->echo_lock);
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->echo_lock);
+ mutex_unlock(&ldata->output_lock);
if (tty->ops->flush_chars)
tty->ops->flush_chars(tty);
@@ -657,72 +699,70 @@ static void process_echoes(struct tty_struct *tty)
/**
* add_echo_byte - add a byte to the echo buffer
* @c: unicode byte to echo
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add a character or operation byte to the echo buffer.
*
* Should be called under the echo lock to protect the echo buffer.
*/
-static void add_echo_byte(unsigned char c, struct tty_struct *tty)
+static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
{
int new_byte_pos;
- if (tty->echo_cnt == N_TTY_BUF_SIZE) {
+ if (ldata->echo_cnt == N_TTY_BUF_SIZE) {
/* Circular buffer is already at capacity */
- new_byte_pos = tty->echo_pos;
+ new_byte_pos = ldata->echo_pos;
/*
* Since the buffer start position needs to be advanced,
* be sure to step by a whole operation byte group.
*/
- if (tty->echo_buf[tty->echo_pos] == ECHO_OP_START) {
- if (tty->echo_buf[(tty->echo_pos + 1) &
+ if (ldata->echo_buf[ldata->echo_pos] == ECHO_OP_START) {
+ if (ldata->echo_buf[(ldata->echo_pos + 1) &
(N_TTY_BUF_SIZE - 1)] ==
ECHO_OP_ERASE_TAB) {
- tty->echo_pos += 3;
- tty->echo_cnt -= 2;
+ ldata->echo_pos += 3;
+ ldata->echo_cnt -= 2;
} else {
- tty->echo_pos += 2;
- tty->echo_cnt -= 1;
+ ldata->echo_pos += 2;
+ ldata->echo_cnt -= 1;
}
} else {
- tty->echo_pos++;
+ ldata->echo_pos++;
}
- tty->echo_pos &= N_TTY_BUF_SIZE - 1;
+ ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
- tty->echo_overrun = 1;
+ ldata->echo_overrun = 1;
} else {
- new_byte_pos = tty->echo_pos + tty->echo_cnt;
+ new_byte_pos = ldata->echo_pos + ldata->echo_cnt;
new_byte_pos &= N_TTY_BUF_SIZE - 1;
- tty->echo_cnt++;
+ ldata->echo_cnt++;
}
- tty->echo_buf[new_byte_pos] = c;
+ ldata->echo_buf[new_byte_pos] = c;
}
/**
* echo_move_back_col - add operation to move back a column
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add an operation to the echo buffer to move back one column.
*
* Locking: echo_lock to protect the echo buffer
*/
-static void echo_move_back_col(struct tty_struct *tty)
+static void echo_move_back_col(struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
-
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_MOVE_BACK_COL, tty);
-
- mutex_unlock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata);
+ mutex_unlock(&ldata->echo_lock);
}
/**
* echo_set_canon_col - add operation to set the canon column
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add an operation to the echo buffer to set the canon column
* to the current column.
@@ -730,21 +770,19 @@ static void echo_move_back_col(struct tty_struct *tty)
* Locking: echo_lock to protect the echo buffer
*/
-static void echo_set_canon_col(struct tty_struct *tty)
+static void echo_set_canon_col(struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
-
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_SET_CANON_COL, tty);
-
- mutex_unlock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_SET_CANON_COL, ldata);
+ mutex_unlock(&ldata->echo_lock);
}
/**
* echo_erase_tab - add operation to erase a tab
* @num_chars: number of character columns already used
* @after_tab: true if num_chars starts after a previous tab
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add an operation to the echo buffer to erase a tab.
*
@@ -758,12 +796,12 @@ static void echo_set_canon_col(struct tty_struct *tty)
*/
static void echo_erase_tab(unsigned int num_chars, int after_tab,
- struct tty_struct *tty)
+ struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_ERASE_TAB, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_ERASE_TAB, ldata);
/* We only need to know this modulo 8 (tab spacing) */
num_chars &= 7;
@@ -772,9 +810,9 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
if (after_tab)
num_chars |= 0x80;
- add_echo_byte(num_chars, tty);
+ add_echo_byte(num_chars, ldata);
- mutex_unlock(&tty->echo_lock);
+ mutex_unlock(&ldata->echo_lock);
}
/**
@@ -790,18 +828,16 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
* Locking: echo_lock to protect the echo buffer
*/
-static void echo_char_raw(unsigned char c, struct tty_struct *tty)
+static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
-
+ mutex_lock(&ldata->echo_lock);
if (c == ECHO_OP_START) {
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_START, ldata);
} else {
- add_echo_byte(c, tty);
+ add_echo_byte(c, ldata);
}
-
- mutex_unlock(&tty->echo_lock);
+ mutex_unlock(&ldata->echo_lock);
}
/**
@@ -820,30 +856,32 @@ static void echo_char_raw(unsigned char c, struct tty_struct *tty)
static void echo_char(unsigned char c, struct tty_struct *tty)
{
- mutex_lock(&tty->echo_lock);
+ struct n_tty_data *ldata = tty->disc_data;
+
+ mutex_lock(&ldata->echo_lock);
if (c == ECHO_OP_START) {
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_START, ldata);
} else {
if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t')
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(c, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(c, ldata);
}
- mutex_unlock(&tty->echo_lock);
+ mutex_unlock(&ldata->echo_lock);
}
/**
* finish_erasing - complete erase
- * @tty: tty doing the erase
+ * @ldata: n_tty data
*/
-static inline void finish_erasing(struct tty_struct *tty)
+static inline void finish_erasing(struct n_tty_data *ldata)
{
- if (tty->erasing) {
- echo_char_raw('/', tty);
- tty->erasing = 0;
+ if (ldata->erasing) {
+ echo_char_raw('/', ldata);
+ ldata->erasing = 0;
}
}
@@ -861,12 +899,13 @@ static inline void finish_erasing(struct tty_struct *tty)
static void eraser(unsigned char c, struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
enum { ERASE, WERASE, KILL } kill_type;
int head, seen_alnums, cnt;
unsigned long flags;
/* FIXME: locking needed ? */
- if (tty->read_head == tty->canon_head) {
+ if (ldata->read_head == ldata->canon_head) {
/* process_output('\a', tty); */ /* what do you think? */
return;
}
@@ -876,24 +915,24 @@ static void eraser(unsigned char c, struct tty_struct *tty)
kill_type = WERASE;
else {
if (!L_ECHO(tty)) {
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
(N_TTY_BUF_SIZE - 1));
- tty->read_head = tty->canon_head;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ ldata->read_head = ldata->canon_head;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
return;
}
if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
(N_TTY_BUF_SIZE - 1));
- tty->read_head = tty->canon_head;
- spin_unlock_irqrestore(&tty->read_lock, flags);
- finish_erasing(tty);
+ ldata->read_head = ldata->canon_head;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
+ finish_erasing(ldata);
echo_char(KILL_CHAR(tty), tty);
/* Add a newline if ECHOK is on and ECHOKE is off. */
if (L_ECHOK(tty))
- echo_char_raw('\n', tty);
+ echo_char_raw('\n', ldata);
return;
}
kill_type = KILL;
@@ -901,14 +940,14 @@ static void eraser(unsigned char c, struct tty_struct *tty)
seen_alnums = 0;
/* FIXME: Locking ?? */
- while (tty->read_head != tty->canon_head) {
- head = tty->read_head;
+ while (ldata->read_head != ldata->canon_head) {
+ head = ldata->read_head;
/* erase a single possibly multibyte character */
do {
head = (head - 1) & (N_TTY_BUF_SIZE-1);
- c = tty->read_buf[head];
- } while (is_continuation(c, tty) && head != tty->canon_head);
+ c = ldata->read_buf[head];
+ } while (is_continuation(c, tty) && head != ldata->canon_head);
/* do not partially erase */
if (is_continuation(c, tty))
@@ -921,30 +960,31 @@ static void eraser(unsigned char c, struct tty_struct *tty)
else if (seen_alnums)
break;
}
- cnt = (tty->read_head - head) & (N_TTY_BUF_SIZE-1);
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_head = head;
- tty->read_cnt -= cnt;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ cnt = (ldata->read_head - head) & (N_TTY_BUF_SIZE-1);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_head = head;
+ ldata->read_cnt -= cnt;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (L_ECHO(tty)) {
if (L_ECHOPRT(tty)) {
- if (!tty->erasing) {
- echo_char_raw('\\', tty);
- tty->erasing = 1;
+ if (!ldata->erasing) {
+ echo_char_raw('\\', ldata);
+ ldata->erasing = 1;
}
/* if cnt > 1, output a multi-byte character */
echo_char(c, tty);
while (--cnt > 0) {
head = (head+1) & (N_TTY_BUF_SIZE-1);
- echo_char_raw(tty->read_buf[head], tty);
- echo_move_back_col(tty);
+ echo_char_raw(ldata->read_buf[head],
+ ldata);
+ echo_move_back_col(ldata);
}
} else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty);
} else if (c == '\t') {
unsigned int num_chars = 0;
int after_tab = 0;
- unsigned long tail = tty->read_head;
+ unsigned long tail = ldata->read_head;
/*
* Count the columns used for characters
@@ -953,9 +993,9 @@ static void eraser(unsigned char c, struct tty_struct *tty)
* This info is used to go back the correct
* number of columns.
*/
- while (tail != tty->canon_head) {
+ while (tail != ldata->canon_head) {
tail = (tail-1) & (N_TTY_BUF_SIZE-1);
- c = tty->read_buf[tail];
+ c = ldata->read_buf[tail];
if (c == '\t') {
after_tab = 1;
break;
@@ -966,25 +1006,25 @@ static void eraser(unsigned char c, struct tty_struct *tty)
num_chars++;
}
}
- echo_erase_tab(num_chars, after_tab, tty);
+ echo_erase_tab(num_chars, after_tab, ldata);
} else {
if (iscntrl(c) && L_ECHOCTL(tty)) {
- echo_char_raw('\b', tty);
- echo_char_raw(' ', tty);
- echo_char_raw('\b', tty);
+ echo_char_raw('\b', ldata);
+ echo_char_raw(' ', ldata);
+ echo_char_raw('\b', ldata);
}
if (!iscntrl(c) || L_ECHOCTL(tty)) {
- echo_char_raw('\b', tty);
- echo_char_raw(' ', tty);
- echo_char_raw('\b', tty);
+ echo_char_raw('\b', ldata);
+ echo_char_raw(' ', ldata);
+ echo_char_raw('\b', ldata);
}
}
}
if (kill_type == ERASE)
break;
}
- if (tty->read_head == tty->canon_head && L_ECHO(tty))
- finish_erasing(tty);
+ if (ldata->read_head == ldata->canon_head && L_ECHO(tty))
+ finish_erasing(ldata);
}
/**
@@ -1023,6 +1063,8 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
static inline void n_tty_receive_break(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
if (I_IGNBRK(tty))
return;
if (I_BRKINT(tty)) {
@@ -1030,10 +1072,10 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
return;
}
if (I_PARMRK(tty)) {
- put_tty_queue('\377', tty);
- put_tty_queue('\0', tty);
+ put_tty_queue('\377', ldata);
+ put_tty_queue('\0', ldata);
}
- put_tty_queue('\0', tty);
+ put_tty_queue('\0', ldata);
wake_up_interruptible(&tty->read_wait);
}
@@ -1052,16 +1094,17 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
static inline void n_tty_receive_overrun(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
char buf[64];
- tty->num_overrun++;
- if (time_before(tty->overrun_time, jiffies - HZ) ||
- time_after(tty->overrun_time, jiffies)) {
+ ldata->num_overrun++;
+ if (time_after(jiffies, ldata->overrun_time + HZ) ||
+ time_after(ldata->overrun_time, jiffies)) {
printk(KERN_WARNING "%s: %d input overrun(s)\n",
tty_name(tty, buf),
- tty->num_overrun);
- tty->overrun_time = jiffies;
- tty->num_overrun = 0;
+ ldata->num_overrun);
+ ldata->overrun_time = jiffies;
+ ldata->num_overrun = 0;
}
}
@@ -1076,16 +1119,18 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty)
static inline void n_tty_receive_parity_error(struct tty_struct *tty,
unsigned char c)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
if (I_IGNPAR(tty))
return;
if (I_PARMRK(tty)) {
- put_tty_queue('\377', tty);
- put_tty_queue('\0', tty);
- put_tty_queue(c, tty);
+ put_tty_queue('\377', ldata);
+ put_tty_queue('\0', ldata);
+ put_tty_queue(c, ldata);
} else if (I_INPCK(tty))
- put_tty_queue('\0', tty);
+ put_tty_queue('\0', ldata);
else
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
wake_up_interruptible(&tty->read_wait);
}
@@ -1101,11 +1146,12 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned long flags;
int parmrk;
- if (tty->raw) {
- put_tty_queue(c, tty);
+ if (ldata->raw) {
+ put_tty_queue(c, ldata);
return;
}
@@ -1115,7 +1161,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
c = tolower(c);
if (L_EXTPROC(tty)) {
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
return;
}
@@ -1143,26 +1189,26 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
* handle specially, do shortcut processing to speed things
* up.
*/
- if (!test_bit(c, tty->process_char_map) || tty->lnext) {
- tty->lnext = 0;
+ if (!test_bit(c, ldata->process_char_map) || ldata->lnext) {
+ ldata->lnext = 0;
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
- if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+ if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
/* beep if no space */
if (L_ECHO(tty))
process_output('\a', tty);
return;
}
if (L_ECHO(tty)) {
- finish_erasing(tty);
+ finish_erasing(ldata);
/* Record the column of first canon char. */
- if (tty->canon_head == tty->read_head)
- echo_set_canon_col(tty);
+ if (ldata->canon_head == ldata->read_head)
+ echo_set_canon_col(ldata);
echo_char(c, tty);
process_echoes(tty);
}
if (parmrk)
- put_tty_queue(c, tty);
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
+ put_tty_queue(c, ldata);
return;
}
@@ -1218,7 +1264,7 @@ send_signal:
} else if (c == '\n' && I_INLCR(tty))
c = '\r';
- if (tty->icanon) {
+ if (ldata->icanon) {
if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
(c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
eraser(c, tty);
@@ -1226,12 +1272,12 @@ send_signal:
return;
}
if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
- tty->lnext = 1;
+ ldata->lnext = 1;
if (L_ECHO(tty)) {
- finish_erasing(tty);
+ finish_erasing(ldata);
if (L_ECHOCTL(tty)) {
- echo_char_raw('^', tty);
- echo_char_raw('\b', tty);
+ echo_char_raw('^', ldata);
+ echo_char_raw('\b', ldata);
process_echoes(tty);
}
}
@@ -1239,34 +1285,34 @@ send_signal:
}
if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
L_IEXTEN(tty)) {
- unsigned long tail = tty->canon_head;
+ unsigned long tail = ldata->canon_head;
- finish_erasing(tty);
+ finish_erasing(ldata);
echo_char(c, tty);
- echo_char_raw('\n', tty);
- while (tail != tty->read_head) {
- echo_char(tty->read_buf[tail], tty);
+ echo_char_raw('\n', ldata);
+ while (tail != ldata->read_head) {
+ echo_char(ldata->read_buf[tail], tty);
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
}
process_echoes(tty);
return;
}
if (c == '\n') {
- if (tty->read_cnt >= N_TTY_BUF_SIZE) {
+ if (ldata->read_cnt >= N_TTY_BUF_SIZE) {
if (L_ECHO(tty))
process_output('\a', tty);
return;
}
if (L_ECHO(tty) || L_ECHONL(tty)) {
- echo_char_raw('\n', tty);
+ echo_char_raw('\n', ldata);
process_echoes(tty);
}
goto handle_newline;
}
if (c == EOF_CHAR(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE)
+ if (ldata->read_cnt >= N_TTY_BUF_SIZE)
return;
- if (tty->canon_head != tty->read_head)
+ if (ldata->canon_head != ldata->read_head)
set_bit(TTY_PUSH, &tty->flags);
c = __DISABLED_CHAR;
goto handle_newline;
@@ -1275,7 +1321,7 @@ send_signal:
(c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
? 1 : 0;
- if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
+ if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
if (L_ECHO(tty))
process_output('\a', tty);
return;
@@ -1285,8 +1331,8 @@ send_signal:
*/
if (L_ECHO(tty)) {
/* Record the column of first canon char. */
- if (tty->canon_head == tty->read_head)
- echo_set_canon_col(tty);
+ if (ldata->canon_head == ldata->read_head)
+ echo_set_canon_col(ldata);
echo_char(c, tty);
process_echoes(tty);
}
@@ -1295,15 +1341,15 @@ send_signal:
* EOL_CHAR and EOL2_CHAR?
*/
if (parmrk)
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
handle_newline:
- spin_lock_irqsave(&tty->read_lock, flags);
- set_bit(tty->read_head, tty->read_flags);
- put_tty_queue_nolock(c, tty);
- tty->canon_head = tty->read_head;
- tty->canon_data++;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ set_bit(ldata->read_head, ldata->read_flags);
+ put_tty_queue_nolock(c, ldata);
+ ldata->canon_head = ldata->read_head;
+ ldata->canon_data++;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait);
@@ -1312,29 +1358,29 @@ handle_newline:
}
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
- if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+ if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
/* beep if no space */
if (L_ECHO(tty))
process_output('\a', tty);
return;
}
if (L_ECHO(tty)) {
- finish_erasing(tty);
+ finish_erasing(ldata);
if (c == '\n')
- echo_char_raw('\n', tty);
+ echo_char_raw('\n', ldata);
else {
/* Record the column of first canon char. */
- if (tty->canon_head == tty->read_head)
- echo_set_canon_col(tty);
+ if (ldata->canon_head == ldata->read_head)
+ echo_set_canon_col(ldata);
echo_char(c, tty);
}
process_echoes(tty);
}
if (parmrk)
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
}
@@ -1369,33 +1415,31 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
+ struct n_tty_data *ldata = tty->disc_data;
const unsigned char *p;
char *f, flags = TTY_NORMAL;
int i;
char buf[64];
unsigned long cpuflags;
- if (!tty->read_buf)
- return;
-
- if (tty->real_raw) {
- spin_lock_irqsave(&tty->read_lock, cpuflags);
- i = min(N_TTY_BUF_SIZE - tty->read_cnt,
- N_TTY_BUF_SIZE - tty->read_head);
+ if (ldata->real_raw) {
+ spin_lock_irqsave(&ldata->read_lock, cpuflags);
+ i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+ N_TTY_BUF_SIZE - ldata->read_head);
i = min(count, i);
- memcpy(tty->read_buf + tty->read_head, cp, i);
- tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt += i;
+ memcpy(ldata->read_buf + ldata->read_head, cp, i);
+ ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt += i;
cp += i;
count -= i;
- i = min(N_TTY_BUF_SIZE - tty->read_cnt,
- N_TTY_BUF_SIZE - tty->read_head);
+ i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+ N_TTY_BUF_SIZE - ldata->read_head);
i = min(count, i);
- memcpy(tty->read_buf + tty->read_head, cp, i);
- tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt += i;
- spin_unlock_irqrestore(&tty->read_lock, cpuflags);
+ memcpy(ldata->read_buf + ldata->read_head, cp, i);
+ ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt += i;
+ spin_unlock_irqrestore(&ldata->read_lock, cpuflags);
} else {
for (i = count, p = cp, f = fp; i; i--, p++) {
if (f)
@@ -1426,7 +1470,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
n_tty_set_room(tty);
- if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
+ if ((!ldata->icanon && (ldata->read_cnt >= tty->minimum_to_wake)) ||
L_EXTPROC(tty)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
@@ -1470,25 +1514,25 @@ int is_ignored(int sig)
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
+ struct n_tty_data *ldata = tty->disc_data;
int canon_change = 1;
- BUG_ON(!tty);
if (old)
canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
if (canon_change) {
- memset(&tty->read_flags, 0, sizeof tty->read_flags);
- tty->canon_head = tty->read_tail;
- tty->canon_data = 0;
- tty->erasing = 0;
+ bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
+ ldata->canon_head = ldata->read_tail;
+ ldata->canon_data = 0;
+ ldata->erasing = 0;
}
- if (canon_change && !L_ICANON(tty) && tty->read_cnt)
+ if (canon_change && !L_ICANON(tty) && ldata->read_cnt)
wake_up_interruptible(&tty->read_wait);
- tty->icanon = (L_ICANON(tty) != 0);
+ ldata->icanon = (L_ICANON(tty) != 0);
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
- tty->raw = 1;
- tty->real_raw = 1;
+ ldata->raw = 1;
+ ldata->real_raw = 1;
n_tty_set_room(tty);
return;
}
@@ -1496,51 +1540,51 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
I_PARMRK(tty)) {
- memset(tty->process_char_map, 0, 256/8);
+ bitmap_zero(ldata->process_char_map, 256);
if (I_IGNCR(tty) || I_ICRNL(tty))
- set_bit('\r', tty->process_char_map);
+ set_bit('\r', ldata->process_char_map);
if (I_INLCR(tty))
- set_bit('\n', tty->process_char_map);
+ set_bit('\n', ldata->process_char_map);
if (L_ICANON(tty)) {
- set_bit(ERASE_CHAR(tty), tty->process_char_map);
- set_bit(KILL_CHAR(tty), tty->process_char_map);
- set_bit(EOF_CHAR(tty), tty->process_char_map);
- set_bit('\n', tty->process_char_map);
- set_bit(EOL_CHAR(tty), tty->process_char_map);
+ set_bit(ERASE_CHAR(tty), ldata->process_char_map);
+ set_bit(KILL_CHAR(tty), ldata->process_char_map);
+ set_bit(EOF_CHAR(tty), ldata->process_char_map);
+ set_bit('\n', ldata->process_char_map);
+ set_bit(EOL_CHAR(tty), ldata->process_char_map);
if (L_IEXTEN(tty)) {
set_bit(WERASE_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
set_bit(LNEXT_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
set_bit(EOL2_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
if (L_ECHO(tty))
set_bit(REPRINT_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
}
}
if (I_IXON(tty)) {
- set_bit(START_CHAR(tty), tty->process_char_map);
- set_bit(STOP_CHAR(tty), tty->process_char_map);
+ set_bit(START_CHAR(tty), ldata->process_char_map);
+ set_bit(STOP_CHAR(tty), ldata->process_char_map);
}
if (L_ISIG(tty)) {
- set_bit(INTR_CHAR(tty), tty->process_char_map);
- set_bit(QUIT_CHAR(tty), tty->process_char_map);
- set_bit(SUSP_CHAR(tty), tty->process_char_map);
+ set_bit(INTR_CHAR(tty), ldata->process_char_map);
+ set_bit(QUIT_CHAR(tty), ldata->process_char_map);
+ set_bit(SUSP_CHAR(tty), ldata->process_char_map);
}
- clear_bit(__DISABLED_CHAR, tty->process_char_map);
- tty->raw = 0;
- tty->real_raw = 0;
+ clear_bit(__DISABLED_CHAR, ldata->process_char_map);
+ ldata->raw = 0;
+ ldata->real_raw = 0;
} else {
- tty->raw = 1;
+ ldata->raw = 1;
if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
(I_IGNPAR(tty) || !I_INPCK(tty)) &&
(tty->driver->flags & TTY_DRIVER_REAL_RAW))
- tty->real_raw = 1;
+ ldata->real_raw = 1;
else
- tty->real_raw = 0;
+ ldata->real_raw = 0;
}
n_tty_set_room(tty);
/* The termios change make the tty ready for I/O */
@@ -1560,15 +1604,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
static void n_tty_close(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
n_tty_flush_buffer(tty);
- if (tty->read_buf) {
- kfree(tty->read_buf);
- tty->read_buf = NULL;
- }
- if (tty->echo_buf) {
- kfree(tty->echo_buf);
- tty->echo_buf = NULL;
- }
+ kfree(ldata->read_buf);
+ kfree(ldata->echo_buf);
+ kfree(ldata);
+ tty->disc_data = NULL;
}
/**
@@ -1583,37 +1625,50 @@ static void n_tty_close(struct tty_struct *tty)
static int n_tty_open(struct tty_struct *tty)
{
- if (!tty)
- return -EINVAL;
+ struct n_tty_data *ldata;
+
+ ldata = kzalloc(sizeof(*ldata), GFP_KERNEL);
+ if (!ldata)
+ goto err;
+
+ ldata->overrun_time = jiffies;
+ mutex_init(&ldata->atomic_read_lock);
+ mutex_init(&ldata->output_lock);
+ mutex_init(&ldata->echo_lock);
+ spin_lock_init(&ldata->read_lock);
/* These are ugly. Currently a malloc failure here can panic */
- if (!tty->read_buf) {
- tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
- if (!tty->read_buf)
- return -ENOMEM;
- }
- if (!tty->echo_buf) {
- tty->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ ldata->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ if (!ldata->read_buf || !ldata->echo_buf)
+ goto err_free_bufs;
- if (!tty->echo_buf)
- return -ENOMEM;
- }
+ tty->disc_data = ldata;
reset_buffer_flags(tty);
tty_unthrottle(tty);
- tty->column = 0;
+ ldata->column = 0;
n_tty_set_termios(tty, NULL);
tty->minimum_to_wake = 1;
tty->closing = 0;
+
return 0;
+err_free_bufs:
+ kfree(ldata->read_buf);
+ kfree(ldata->echo_buf);
+ kfree(ldata);
+err:
+ return -ENOMEM;
}
static inline int input_available_p(struct tty_struct *tty, int amt)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
tty_flush_to_ldisc(tty);
- if (tty->icanon && !L_EXTPROC(tty)) {
- if (tty->canon_data)
+ if (ldata->icanon && !L_EXTPROC(tty)) {
+ if (ldata->canon_data)
return 1;
- } else if (tty->read_cnt >= (amt ? amt : 1))
+ } else if (ldata->read_cnt >= (amt ? amt : 1))
return 1;
return 0;
@@ -1632,7 +1687,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
* buffer, and once to drain the space from the (physical) beginning of
* the buffer to head pointer.
*
- * Called under the tty->atomic_read_lock sem
+ * Called under the ldata->atomic_read_lock sem
*
*/
@@ -1641,29 +1696,31 @@ static int copy_from_read_buf(struct tty_struct *tty,
size_t *nr)
{
+ struct n_tty_data *ldata = tty->disc_data;
int retval;
size_t n;
unsigned long flags;
bool is_eof;
retval = 0;
- spin_lock_irqsave(&tty->read_lock, flags);
- n = min(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ n = min(ldata->read_cnt, N_TTY_BUF_SIZE - ldata->read_tail);
n = min(*nr, n);
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (n) {
- retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+ retval = copy_to_user(*b, &ldata->read_buf[ldata->read_tail], n);
n -= retval;
is_eof = n == 1 &&
- tty->read_buf[tty->read_tail] == EOF_CHAR(tty);
- tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt -= n;
+ ldata->read_buf[ldata->read_tail] == EOF_CHAR(tty);
+ tty_audit_add_data(tty, &ldata->read_buf[ldata->read_tail], n,
+ ldata->icanon);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_tail = (ldata->read_tail + n) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt -= n;
/* Turn single EOF into zero-length read */
- if (L_EXTPROC(tty) && tty->icanon && is_eof && !tty->read_cnt)
+ if (L_EXTPROC(tty) && ldata->icanon && is_eof && !ldata->read_cnt)
n = 0;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
*b += n;
*nr -= n;
}
@@ -1730,6 +1787,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned char __user *b = buf;
DECLARE_WAITQUEUE(wait, current);
int c;
@@ -1741,17 +1799,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
int packet;
do_it_again:
-
- if (WARN_ON(!tty->read_buf))
- return -EAGAIN;
-
c = job_control(tty, file);
if (c < 0)
return c;
minimum = time = 0;
timeout = MAX_SCHEDULE_TIMEOUT;
- if (!tty->icanon) {
+ if (!ldata->icanon) {
time = (HZ / 10) * TIME_CHAR(tty);
minimum = MIN_CHAR(tty);
if (minimum) {
@@ -1774,10 +1828,10 @@ do_it_again:
* Internal serialization of reads.
*/
if (file->f_flags & O_NONBLOCK) {
- if (!mutex_trylock(&tty->atomic_read_lock))
+ if (!mutex_trylock(&ldata->atomic_read_lock))
return -EAGAIN;
} else {
- if (mutex_lock_interruptible(&tty->atomic_read_lock))
+ if (mutex_lock_interruptible(&ldata->atomic_read_lock))
return -ERESTARTSYS;
}
packet = tty->packet;
@@ -1830,7 +1884,6 @@ do_it_again:
/* FIXME: does n_tty_set_room need locking ? */
n_tty_set_room(tty);
timeout = schedule_timeout(timeout);
- BUG_ON(!tty->read_buf);
continue;
}
__set_current_state(TASK_RUNNING);
@@ -1845,45 +1898,45 @@ do_it_again:
nr--;
}
- if (tty->icanon && !L_EXTPROC(tty)) {
+ if (ldata->icanon && !L_EXTPROC(tty)) {
/* N.B. avoid overrun if nr == 0 */
- spin_lock_irqsave(&tty->read_lock, flags);
- while (nr && tty->read_cnt) {
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ while (nr && ldata->read_cnt) {
int eol;
- eol = test_and_clear_bit(tty->read_tail,
- tty->read_flags);
- c = tty->read_buf[tty->read_tail];
- tty->read_tail = ((tty->read_tail+1) &
+ eol = test_and_clear_bit(ldata->read_tail,
+ ldata->read_flags);
+ c = ldata->read_buf[ldata->read_tail];
+ ldata->read_tail = ((ldata->read_tail+1) &
(N_TTY_BUF_SIZE-1));
- tty->read_cnt--;
+ ldata->read_cnt--;
if (eol) {
/* this test should be redundant:
* we shouldn't be reading data if
* canon_data is 0
*/
- if (--tty->canon_data < 0)
- tty->canon_data = 0;
+ if (--ldata->canon_data < 0)
+ ldata->canon_data = 0;
}
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (!eol || (c != __DISABLED_CHAR)) {
if (tty_put_user(tty, c, b++)) {
retval = -EFAULT;
b--;
- spin_lock_irqsave(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
break;
}
nr--;
}
if (eol) {
tty_audit_push(tty);
- spin_lock_irqsave(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
break;
}
- spin_lock_irqsave(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
}
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (retval)
break;
} else {
@@ -1915,7 +1968,7 @@ do_it_again:
if (time)
timeout = time;
}
- mutex_unlock(&tty->atomic_read_lock);
+ mutex_unlock(&ldata->atomic_read_lock);
remove_wait_queue(&tty->read_wait, &wait);
if (!waitqueue_active(&tty->read_wait))
@@ -2076,19 +2129,19 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
return mask;
}
-static unsigned long inq_canon(struct tty_struct *tty)
+static unsigned long inq_canon(struct n_tty_data *ldata)
{
int nr, head, tail;
- if (!tty->canon_data)
+ if (!ldata->canon_data)
return 0;
- head = tty->canon_head;
- tail = tty->read_tail;
+ head = ldata->canon_head;
+ tail = ldata->read_tail;
nr = (head - tail) & (N_TTY_BUF_SIZE-1);
/* Skip EOF-chars.. */
while (head != tail) {
- if (test_bit(tail, tty->read_flags) &&
- tty->read_buf[tail] == __DISABLED_CHAR)
+ if (test_bit(tail, ldata->read_flags) &&
+ ldata->read_buf[tail] == __DISABLED_CHAR)
nr--;
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
}
@@ -2098,6 +2151,7 @@ static unsigned long inq_canon(struct tty_struct *tty)
static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct n_tty_data *ldata = tty->disc_data;
int retval;
switch (cmd) {
@@ -2105,9 +2159,9 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
case TIOCINQ:
/* FIXME: Locking */
- retval = tty->read_cnt;
+ retval = ldata->read_cnt;
if (L_ICANON(tty))
- retval = inq_canon(tty);
+ retval = inq_canon(ldata);
return put_user(retval, (unsigned int __user *) arg);
default:
return n_tty_ioctl_helper(tty, file, cmd, arg);
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index a82b39939a9..4219f040adb 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -4,9 +4,6 @@
* Added support for a Unix98-style ptmx device.
* -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
*
- * When reading this code see also fs/devpts. In particular note that the
- * driver_data field is used by the devpts side as a binding to the devpts
- * inode.
*/
#include <linux/module.h>
@@ -59,7 +56,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
#ifdef CONFIG_UNIX98_PTYS
if (tty->driver == ptm_driver) {
mutex_lock(&devpts_mutex);
- devpts_pty_kill(tty->link);
+ devpts_pty_kill(tty->link->driver_data);
mutex_unlock(&devpts_mutex);
}
#endif
@@ -96,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty)
static int pty_space(struct tty_struct *to)
{
- int n = 8192 - to->buf.memory_used;
+ int n = 8192 - to->port->buf.memory_used;
if (n < 0)
return 0;
return n;
@@ -348,6 +345,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
tty_port_init(ports[1]);
o_tty->port = ports[0];
tty->port = ports[1];
+ o_tty->port->itty = o_tty;
tty_driver_kref_get(driver);
tty->count++;
@@ -366,8 +364,15 @@ err:
return retval;
}
+/* this is called once with whichever end is closed last */
+static void pty_unix98_shutdown(struct tty_struct *tty)
+{
+ devpts_kill_index(tty->driver_data, tty->index);
+}
+
static void pty_cleanup(struct tty_struct *tty)
{
+ tty->port->itty = NULL;
kfree(tty->port);
}
@@ -547,7 +552,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
struct tty_struct *tty;
mutex_lock(&devpts_mutex);
- tty = devpts_get_tty(pts_inode, idx);
+ tty = devpts_get_priv(pts_inode);
mutex_unlock(&devpts_mutex);
/* Master must be open before slave */
if (!tty)
@@ -581,6 +586,7 @@ static const struct tty_operations ptm_unix98_ops = {
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
.resize = pty_resize,
+ .shutdown = pty_unix98_shutdown,
.cleanup = pty_cleanup
};
@@ -596,6 +602,7 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
+ .shutdown = pty_unix98_shutdown,
.cleanup = pty_cleanup,
};
@@ -614,6 +621,7 @@ static const struct tty_operations pty_unix98_ops = {
static int ptmx_open(struct inode *inode, struct file *filp)
{
struct tty_struct *tty;
+ struct inode *slave_inode;
int retval;
int index;
@@ -650,15 +658,21 @@ static int ptmx_open(struct inode *inode, struct file *filp)
tty_add_file(tty, filp);
- retval = devpts_pty_new(inode, tty->link);
- if (retval)
+ slave_inode = devpts_pty_new(inode,
+ MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
+ tty->link);
+ if (IS_ERR(slave_inode)) {
+ retval = PTR_ERR(slave_inode);
goto err_release;
+ }
retval = ptm_driver->ops->open(tty, filp);
if (retval)
goto err_release;
tty_unlock(tty);
+ tty->driver_data = inode;
+ tty->link->driver_data = slave_inode;
return 0;
err_release:
tty_unlock(tty);
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 3ba4234592b..5ccbd90540c 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -2349,16 +2349,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
serial_port_out(port, UART_EFR, efr);
}
-#ifdef CONFIG_ARCH_OMAP1
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
- if (cpu_is_omap1510() && is_omap_port(up)) {
+ if (is_omap1510_8250(up)) {
if (baud == 115200) {
quot = 1;
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
} else
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
}
-#endif
/*
* For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
@@ -2439,10 +2437,9 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
{
if (pt->port.iotype == UPIO_AU)
return 0x1000;
-#ifdef CONFIG_ARCH_OMAP1
- if (is_omap_port(pt))
+ if (is_omap1_8250(pt))
return 0x16 << pt->port.regshift;
-#endif
+
return 8 << pt->port.regshift;
}
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 5a76f9c8d36..3b4ea84898c 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -106,3 +106,39 @@ static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { }
#endif
+#ifdef CONFIG_ARCH_OMAP1
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+ int res;
+
+ switch (pt->port.mapbase) {
+ case OMAP1_UART1_BASE:
+ case OMAP1_UART2_BASE:
+ case OMAP1_UART3_BASE:
+ res = 1;
+ break;
+ default:
+ res = 0;
+ break;
+ }
+
+ return res;
+}
+
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+ if (!cpu_is_omap1510())
+ return 0;
+
+ return is_omap1_8250(pt);
+}
+#else
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+ return 0;
+}
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+ return 0;
+}
+#endif
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index eaafb98debe..843a150ba10 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -140,7 +140,7 @@ static void __init init_port(struct early_serial8250_device *device)
serial_out(port, UART_FCR, 0); /* no fifo */
serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
- divisor = port->uartclk / (16 * device->baud);
+ divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
c = serial_in(port, UART_LCR);
serial_out(port, UART_LCR, c | UART_LCR_DLAB);
serial_out(port, UART_DLL, divisor & 0xff);
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 2bc28a59d38..1ab1d2c66de 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1239,6 +1239,7 @@ static int __devexit max310x_remove(struct spi_device *spi)
static const struct spi_device_id max310x_id_table[] = {
{ "max3107", MAX310X_TYPE_MAX3107 },
{ "max3108", MAX310X_TYPE_MAX3108 },
+ { }
};
MODULE_DEVICE_TABLE(spi, max310x_id_table);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 7f04717176a..740458ca62c 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -530,16 +530,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
switch (level) {
case 3:
if (!IS_ERR(ourport->baudclk))
- clk_disable(ourport->baudclk);
+ clk_disable_unprepare(ourport->baudclk);
- clk_disable(ourport->clk);
+ clk_disable_unprepare(ourport->clk);
break;
case 0:
- clk_enable(ourport->clk);
+ clk_prepare_enable(ourport->clk);
if (!IS_ERR(ourport->baudclk))
- clk_enable(ourport->baudclk);
+ clk_prepare_enable(ourport->baudclk);
break;
default:
@@ -713,11 +713,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
s3c24xx_serial_setsource(port, clk_sel);
if (!IS_ERR(ourport->baudclk)) {
- clk_disable(ourport->baudclk);
+ clk_disable_unprepare(ourport->baudclk);
ourport->baudclk = ERR_PTR(-EINVAL);
}
- clk_enable(clk);
+ clk_prepare_enable(clk);
ourport->baudclk = clk;
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
@@ -1287,9 +1287,9 @@ static int s3c24xx_serial_resume(struct device *dev)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (port) {
- clk_enable(ourport->clk);
+ clk_prepare_enable(ourport->clk);
s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
- clk_disable(ourport->clk);
+ clk_disable_unprepare(ourport->clk);
uart_resume_port(&s3c24xx_uart_drv, port);
}
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index b0b39b823cc..6953dc82850 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -23,7 +23,7 @@ struct tty_audit_buf {
};
static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
- int icanon)
+ unsigned icanon)
{
struct tty_audit_buf *buf;
@@ -239,7 +239,8 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
* if TTY auditing is disabled or out of memory. Otherwise, return a new
* reference to the buffer.
*/
-static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
+static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
+ unsigned icanon)
{
struct tty_audit_buf *buf, *buf2;
@@ -257,7 +258,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
buf2 = tty_audit_buf_alloc(tty->driver->major,
tty->driver->minor_start + tty->index,
- tty->icanon);
+ icanon);
if (buf2 == NULL) {
audit_log_lost("out of memory in TTY auditing");
return NULL;
@@ -287,7 +288,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
* Audit @data of @size from @tty, if necessary.
*/
void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
- size_t size)
+ size_t size, unsigned icanon)
{
struct tty_audit_buf *buf;
int major, minor;
@@ -299,7 +300,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
&& tty->driver->subtype == PTY_TYPE_MASTER)
return;
- buf = tty_audit_buf_get(tty);
+ buf = tty_audit_buf_get(tty, icanon);
if (!buf)
return;
@@ -307,11 +308,11 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
major = tty->driver->major;
minor = tty->driver->minor_start + tty->index;
if (buf->major != major || buf->minor != minor
- || buf->icanon != tty->icanon) {
+ || buf->icanon != icanon) {
tty_audit_buf_push_current(buf);
buf->major = major;
buf->minor = minor;
- buf->icanon = tty->icanon;
+ buf->icanon = icanon;
}
do {
size_t run;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 91e326ffe7d..6cf87d7afb7 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -27,19 +27,21 @@
* Locking: none
*/
-void tty_buffer_free_all(struct tty_struct *tty)
+void tty_buffer_free_all(struct tty_port *port)
{
+ struct tty_bufhead *buf = &port->buf;
struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
+
+ while ((thead = buf->head) != NULL) {
+ buf->head = thead->next;
kfree(thead);
}
- while ((thead = tty->buf.free) != NULL) {
- tty->buf.free = thead->next;
+ while ((thead = buf->free) != NULL) {
+ buf->free = thead->next;
kfree(thead);
}
- tty->buf.tail = NULL;
- tty->buf.memory_used = 0;
+ buf->tail = NULL;
+ buf->memory_used = 0;
}
/**
@@ -54,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty)
* Locking: Caller must hold tty->buf.lock
*/
-static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
{
struct tty_buffer *p;
- if (tty->buf.memory_used + size > 65536)
+ if (port->buf.memory_used + size > 65536)
return NULL;
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if (p == NULL)
@@ -70,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
- tty->buf.memory_used += size;
+ port->buf.memory_used += size;
return p;
}
@@ -85,17 +87,19 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
* Locking: Caller must hold tty->buf.lock
*/
-static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
{
+ struct tty_bufhead *buf = &port->buf;
+
/* Dumb strategy for now - should keep some stats */
- tty->buf.memory_used -= b->size;
- WARN_ON(tty->buf.memory_used < 0);
+ buf->memory_used -= b->size;
+ WARN_ON(buf->memory_used < 0);
if (b->size >= 512)
kfree(b);
else {
- b->next = tty->buf.free;
- tty->buf.free = b;
+ b->next = buf->free;
+ buf->free = b;
}
}
@@ -110,15 +114,16 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
* Locking: Caller must hold tty->buf.lock
*/
-static void __tty_buffer_flush(struct tty_struct *tty)
+static void __tty_buffer_flush(struct tty_port *port)
{
+ struct tty_bufhead *buf = &port->buf;
struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
- tty_buffer_free(tty, thead);
+ while ((thead = buf->head) != NULL) {
+ buf->head = thead->next;
+ tty_buffer_free(port, thead);
}
- tty->buf.tail = NULL;
+ buf->tail = NULL;
}
/**
@@ -134,21 +139,24 @@ static void __tty_buffer_flush(struct tty_struct *tty)
void tty_buffer_flush(struct tty_struct *tty)
{
+ struct tty_port *port = tty->port;
+ struct tty_bufhead *buf = &port->buf;
unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
+
+ spin_lock_irqsave(&buf->lock, flags);
/* If the data is being pushed to the tty layer then we can't
process it here. Instead set a flag and the flush_to_ldisc
path will process the flush request before it exits */
- if (test_bit(TTY_FLUSHING, &tty->flags)) {
- set_bit(TTY_FLUSHPENDING, &tty->flags);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ if (test_bit(TTYP_FLUSHING, &port->iflags)) {
+ set_bit(TTYP_FLUSHPENDING, &port->iflags);
+ spin_unlock_irqrestore(&buf->lock, flags);
wait_event(tty->read_wait,
- test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
+ test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
return;
} else
- __tty_buffer_flush(tty);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ __tty_buffer_flush(port);
+ spin_unlock_irqrestore(&buf->lock, flags);
}
/**
@@ -163,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty)
* Locking: Caller must hold tty->buf.lock
*/
-static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
{
- struct tty_buffer **tbh = &tty->buf.free;
+ struct tty_buffer **tbh = &port->buf.free;
while ((*tbh) != NULL) {
struct tty_buffer *t = *tbh;
if (t->size >= size) {
@@ -174,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
t->used = 0;
t->commit = 0;
t->read = 0;
- tty->buf.memory_used += t->size;
+ port->buf.memory_used += t->size;
return t;
}
tbh = &((*tbh)->next);
}
/* Round the buffer size out */
size = (size + 0xFF) & ~0xFF;
- return tty_buffer_alloc(tty, size);
+ return tty_buffer_alloc(port, size);
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
}
@@ -192,29 +200,31 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
*
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
- * Locking: Caller must hold tty->buf.lock
+ * Locking: Caller must hold port->buf.lock
*/
-static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
+static int __tty_buffer_request_room(struct tty_port *port, size_t size)
{
+ struct tty_bufhead *buf = &port->buf;
struct tty_buffer *b, *n;
int left;
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
remove this conditional if its worth it. This would be invisible
to the callers */
- if ((b = tty->buf.tail) != NULL)
+ b = buf->tail;
+ if (b != NULL)
left = b->size - b->used;
else
left = 0;
if (left < size) {
/* This is the slow path - looking for new buffers to use */
- if ((n = tty_buffer_find(tty, size)) != NULL) {
+ if ((n = tty_buffer_find(port, size)) != NULL) {
if (b != NULL) {
b->next = n;
b->commit = b->used;
} else
- tty->buf.head = n;
- tty->buf.tail = n;
+ buf->head = n;
+ buf->tail = n;
} else
size = left;
}
@@ -231,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
*
- * Locking: Takes tty->buf.lock
+ * Locking: Takes port->buf.lock
*/
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
+ struct tty_port *port = tty->port;
unsigned long flags;
int length;
- spin_lock_irqsave(&tty->buf.lock, flags);
- length = __tty_buffer_request_room(tty, size);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_lock_irqsave(&port->buf.lock, flags);
+ length = __tty_buffer_request_room(port, size);
+ spin_unlock_irqrestore(&port->buf.lock, flags);
return length;
}
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
@@ -255,12 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
* Queue a series of bytes to the tty buffering. All the characters
* passed are marked with the supplied flag. Returns the number added.
*
- * Locking: Called functions may take tty->buf.lock
+ * Locking: Called functions may take port->buf.lock
*/
int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
const unsigned char *chars, char flag, size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -268,18 +280,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
unsigned long flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, flags);
- space = __tty_buffer_request_room(tty, goal);
- tb = tty->buf.tail;
+ spin_lock_irqsave(&buf->lock, flags);
+ space = __tty_buffer_request_room(tty->port, goal);
+ tb = buf->tail;
/* If there is no space then tb may be NULL */
if (unlikely(space == 0)) {
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
break;
}
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memset(tb->flag_buf_ptr + tb->used, flag, space);
tb->used += space;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
copied += space;
chars += space;
/* There is a small chance that we need to split the data over
@@ -300,12 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
* the flags array indicates the status of the character. Returns the
* number added.
*
- * Locking: Called functions may take tty->buf.lock
+ * Locking: Called functions may take port->buf.lock
*/
int tty_insert_flip_string_flags(struct tty_struct *tty,
const unsigned char *chars, const char *flags, size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -313,18 +326,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
unsigned long __flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, __flags);
- space = __tty_buffer_request_room(tty, goal);
- tb = tty->buf.tail;
+ spin_lock_irqsave(&buf->lock, __flags);
+ space = __tty_buffer_request_room(tty->port, goal);
+ tb = buf->tail;
/* If there is no space then tb may be NULL */
if (unlikely(space == 0)) {
- spin_unlock_irqrestore(&tty->buf.lock, __flags);
+ spin_unlock_irqrestore(&buf->lock, __flags);
break;
}
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memcpy(tb->flag_buf_ptr + tb->used, flags, space);
tb->used += space;
- spin_unlock_irqrestore(&tty->buf.lock, __flags);
+ spin_unlock_irqrestore(&buf->lock, __flags);
copied += space;
chars += space;
flags += space;
@@ -342,18 +355,23 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
* Takes any pending buffers and transfers their ownership to the
* ldisc side of the queue. It then schedules those characters for
* processing by the line discipline.
+ * Note that this function can only be used when the low_latency flag
+ * is unset. Otherwise the workqueue won't be flushed.
*
- * Locking: Takes tty->buf.lock
+ * Locking: Takes port->buf.lock
*/
void tty_schedule_flip(struct tty_struct *tty)
{
+ struct tty_bufhead *buf = &tty->port->buf;
unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL)
- tty->buf.tail->commit = tty->buf.tail->used;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- schedule_work(&tty->buf.work);
+ WARN_ON(tty->low_latency);
+
+ spin_lock_irqsave(&buf->lock, flags);
+ if (buf->tail != NULL)
+ buf->tail->commit = buf->tail->used;
+ spin_unlock_irqrestore(&buf->lock, flags);
+ schedule_work(&buf->work);
}
EXPORT_SYMBOL(tty_schedule_flip);
@@ -369,26 +387,27 @@ EXPORT_SYMBOL(tty_schedule_flip);
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
*
- * Locking: May call functions taking tty->buf.lock
+ * Locking: May call functions taking port->buf.lock
*/
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
- size_t size)
+ size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int space;
unsigned long flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, flags);
- space = __tty_buffer_request_room(tty, size);
+ spin_lock_irqsave(&buf->lock, flags);
+ space = __tty_buffer_request_room(tty->port, size);
- tb = tty->buf.tail;
+ tb = buf->tail;
if (likely(space)) {
*chars = tb->char_buf_ptr + tb->used;
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
tb->used += space;
}
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
return space;
}
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
@@ -406,26 +425,27 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
*
- * Locking: May call functions taking tty->buf.lock
+ * Locking: May call functions taking port->buf.lock
*/
int tty_prepare_flip_string_flags(struct tty_struct *tty,
unsigned char **chars, char **flags, size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int space;
unsigned long __flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, __flags);
- space = __tty_buffer_request_room(tty, size);
+ spin_lock_irqsave(&buf->lock, __flags);
+ space = __tty_buffer_request_room(tty->port, size);
- tb = tty->buf.tail;
+ tb = buf->tail;
if (likely(space)) {
*chars = tb->char_buf_ptr + tb->used;
*flags = tb->flag_buf_ptr + tb->used;
tb->used += space;
}
- spin_unlock_irqrestore(&tty->buf.lock, __flags);
+ spin_unlock_irqrestore(&buf->lock, __flags);
return space;
}
EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
@@ -446,20 +466,25 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
static void flush_to_ldisc(struct work_struct *work)
{
- struct tty_struct *tty =
- container_of(work, struct tty_struct, buf.work);
+ struct tty_port *port = container_of(work, struct tty_port, buf.work);
+ struct tty_bufhead *buf = &port->buf;
+ struct tty_struct *tty;
unsigned long flags;
struct tty_ldisc *disc;
+ tty = port->itty;
+ if (WARN_RATELIMIT(tty == NULL, "tty is NULL"))
+ return;
+
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
return;
- spin_lock_irqsave(&tty->buf.lock, flags);
+ spin_lock_irqsave(&buf->lock, flags);
- if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+ if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) {
struct tty_buffer *head;
- while ((head = tty->buf.head) != NULL) {
+ while ((head = buf->head) != NULL) {
int count;
char *char_buf;
unsigned char *flag_buf;
@@ -468,14 +493,14 @@ static void flush_to_ldisc(struct work_struct *work)
if (!count) {
if (head->next == NULL)
break;
- tty->buf.head = head->next;
- tty_buffer_free(tty, head);
+ buf->head = head->next;
+ tty_buffer_free(port, head);
continue;
}
/* Ldisc or user is trying to flush the buffers
we are feeding to the ldisc, stop feeding the
line discipline as we want to empty the queue */
- if (test_bit(TTY_FLUSHPENDING, &tty->flags))
+ if (test_bit(TTYP_FLUSHPENDING, &port->iflags))
break;
if (!tty->receive_room)
break;
@@ -484,22 +509,22 @@ static void flush_to_ldisc(struct work_struct *work)
char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read;
head->read += count;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
disc->ops->receive_buf(tty, char_buf,
flag_buf, count);
- spin_lock_irqsave(&tty->buf.lock, flags);
+ spin_lock_irqsave(&buf->lock, flags);
}
- clear_bit(TTY_FLUSHING, &tty->flags);
+ clear_bit(TTYP_FLUSHING, &port->iflags);
}
/* We may have a deferred request to flush the input buffer,
if so pull the chain under the lock and empty the queue */
- if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
- __tty_buffer_flush(tty);
- clear_bit(TTY_FLUSHPENDING, &tty->flags);
+ if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
+ __tty_buffer_flush(port);
+ clear_bit(TTYP_FLUSHPENDING, &port->iflags);
wake_up(&tty->read_wait);
}
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
tty_ldisc_deref(disc);
}
@@ -514,7 +539,8 @@ static void flush_to_ldisc(struct work_struct *work)
*/
void tty_flush_to_ldisc(struct tty_struct *tty)
{
- flush_work(&tty->buf.work);
+ if (!tty->low_latency)
+ flush_work(&tty->port->buf.work);
}
/**
@@ -532,16 +558,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
void tty_flip_buffer_push(struct tty_struct *tty)
{
+ struct tty_bufhead *buf = &tty->port->buf;
unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL)
- tty->buf.tail->commit = tty->buf.tail->used;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+ spin_lock_irqsave(&buf->lock, flags);
+ if (buf->tail != NULL)
+ buf->tail->commit = buf->tail->used;
+ spin_unlock_irqrestore(&buf->lock, flags);
if (tty->low_latency)
- flush_to_ldisc(&tty->buf.work);
+ flush_to_ldisc(&buf->work);
else
- schedule_work(&tty->buf.work);
+ schedule_work(&buf->work);
}
EXPORT_SYMBOL(tty_flip_buffer_push);
@@ -555,13 +583,15 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
* Locking: none
*/
-void tty_buffer_init(struct tty_struct *tty)
+void tty_buffer_init(struct tty_port *port)
{
- spin_lock_init(&tty->buf.lock);
- tty->buf.head = NULL;
- tty->buf.tail = NULL;
- tty->buf.free = NULL;
- tty->buf.memory_used = 0;
- INIT_WORK(&tty->buf.work, flush_to_ldisc);
+ struct tty_bufhead *buf = &port->buf;
+
+ spin_lock_init(&buf->lock);
+ buf->head = NULL;
+ buf->tail = NULL;
+ buf->free = NULL;
+ buf->memory_used = 0;
+ INIT_WORK(&buf->work, flush_to_ldisc);
}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 2ea176b2280..a3eba7f359e 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -186,7 +186,6 @@ void free_tty_struct(struct tty_struct *tty)
if (tty->dev)
put_device(tty->dev);
kfree(tty->write_buf);
- tty_buffer_free_all(tty);
tty->magic = 0xDEADDEAD;
kfree(tty);
}
@@ -1417,6 +1416,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
__func__, tty->driver->name);
+ tty->port->itty = tty;
+
/*
* Structures all installed ... call the ldisc open routines.
* If we fail here just call release_tty to clean up. No need
@@ -1552,6 +1553,7 @@ static void release_tty(struct tty_struct *tty, int idx)
tty->ops->shutdown(tty);
tty_free_termios(tty);
tty_driver_remove_tty(tty->driver, tty);
+ tty->port->itty = NULL;
if (tty->link)
tty_kref_put(tty->link);
@@ -1625,7 +1627,6 @@ int tty_release(struct inode *inode, struct file *filp)
struct tty_struct *tty = file_tty(filp);
struct tty_struct *o_tty;
int pty_master, tty_closing, o_tty_closing, do_sleep;
- int devpts;
int idx;
char buf[64];
@@ -1640,7 +1641,6 @@ int tty_release(struct inode *inode, struct file *filp)
idx = tty->index;
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
- devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
/* Review: parallel close */
o_tty = tty->link;
@@ -1799,9 +1799,6 @@ int tty_release(struct inode *inode, struct file *filp)
release_tty(tty, idx);
mutex_unlock(&tty_mutex);
- /* Make this pty number available for reallocation */
- if (devpts)
- devpts_kill_index(inode, idx);
return 0;
}
@@ -2937,19 +2934,13 @@ void initialize_tty_struct(struct tty_struct *tty,
tty_ldisc_init(tty);
tty->session = NULL;
tty->pgrp = NULL;
- tty->overrun_time = jiffies;
- tty_buffer_init(tty);
mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
INIT_WORK(&tty->hangup_work, do_tty_hangup);
- mutex_init(&tty->atomic_read_lock);
mutex_init(&tty->atomic_write_lock);
- mutex_init(&tty->output_lock);
- mutex_init(&tty->echo_lock);
- spin_lock_init(&tty->read_lock);
spin_lock_init(&tty->ctrl_lock);
INIT_LIST_HEAD(&tty->tty_files);
INIT_WORK(&tty->SAK_work, do_SAK_work);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 0f2a2c5e704..f4e6754525d 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -512,7 +512,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
static int tty_ldisc_halt(struct tty_struct *tty)
{
clear_bit(TTY_LDISC, &tty->flags);
- return cancel_work_sync(&tty->buf.work);
+ return cancel_work_sync(&tty->port->buf.work);
}
/**
@@ -525,7 +525,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
{
flush_work(&tty->hangup_work);
flush_work(&tty->SAK_work);
- flush_work(&tty->buf.work);
+ flush_work(&tty->port->buf.work);
}
/**
@@ -704,9 +704,9 @@ enable:
/* Restart the work queue in case no characters kick it off. Safe if
already running */
if (work)
- schedule_work(&tty->buf.work);
+ schedule_work(&tty->port->buf.work);
if (o_work)
- schedule_work(&o_tty->buf.work);
+ schedule_work(&o_tty->port->buf.work);
mutex_unlock(&tty->ldisc_mutex);
tty_unlock(tty);
return retval;
@@ -817,7 +817,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
*/
clear_bit(TTY_LDISC, &tty->flags);
tty_unlock(tty);
- cancel_work_sync(&tty->buf.work);
+ cancel_work_sync(&tty->port->buf.work);
mutex_unlock(&tty->ldisc_mutex);
retry:
tty_lock(tty);
@@ -897,6 +897,11 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
static void tty_ldisc_kill(struct tty_struct *tty)
{
+ /* There cannot be users from userspace now. But there still might be
+ * drivers holding a reference via tty_ldisc_ref. Do not steal them the
+ * ldisc until they are done. */
+ tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
+
mutex_lock(&tty->ldisc_mutex);
/*
* Now kill off the ldisc
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index d7bdd8d0c23..416b42f7c34 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -21,6 +21,7 @@
void tty_port_init(struct tty_port *port)
{
memset(port, 0, sizeof(*port));
+ tty_buffer_init(port);
init_waitqueue_head(&port->open_wait);
init_waitqueue_head(&port->close_wait);
init_waitqueue_head(&port->delta_msr_wait);
@@ -126,6 +127,7 @@ static void tty_port_destructor(struct kref *kref)
struct tty_port *port = container_of(kref, struct tty_port, kref);
if (port->xmit_buf)
free_page((unsigned long)port->xmit_buf);
+ tty_buffer_free_all(port);
if (port->ops->destruct)
port->ops->destruct(port);
else
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 8e9b4be97a2..60b7b692605 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -341,15 +341,11 @@ int paste_selection(struct tty_struct *tty)
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
-
console_lock();
poke_blanked_console();
console_unlock();
- /* FIXME: wtf is this supposed to achieve ? */
- ld = tty_ldisc_ref(tty);
- if (!ld)
- ld = tty_ldisc_ref_wait(tty);
+ ld = tty_ldisc_ref_wait(tty);
/* FIXME: this is completely unsafe */
add_wait_queue(&vc->paste_wait, &wait);
@@ -361,8 +357,7 @@ int paste_selection(struct tty_struct *tty)
}
count = sel_buffer_lth - pasted;
count = min(count, tty->receive_room);
- tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
- NULL, count);
+ ld->ops->receive_buf(tty, sel_buffer + pasted, NULL, count);
pasted += count;
}
remove_wait_queue(&vc->paste_wait, &wait);
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 6f3ea9bbc81..c48b93813fc 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -97,6 +97,7 @@ config UIO_NETX
config UIO_PRUSS
tristate "Texas Instruments PRUSS driver"
depends on ARCH_DAVINCI_DA850
+ select GENERIC_ALLOCATOR
help
PRUSS driver for OMAPL138/DA850/AM18XX devices
PRUSS driver requires user space components, examples and user space
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index 33a7a273b45..f8738de342b 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -25,7 +25,7 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <mach/sram.h>
+#include <linux/genalloc.h>
#define DRV_NAME "pruss_uio"
#define DRV_VERSION "1.0"
@@ -65,10 +65,11 @@ struct uio_pruss_dev {
dma_addr_t sram_paddr;
dma_addr_t ddr_paddr;
void __iomem *prussio_vaddr;
- void *sram_vaddr;
+ unsigned long sram_vaddr;
void *ddr_vaddr;
unsigned int hostirq_start;
unsigned int pintc_base;
+ struct gen_pool *sram_pool;
};
static irqreturn_t pruss_handler(int irq, struct uio_info *info)
@@ -106,7 +107,9 @@ static void pruss_cleanup(struct platform_device *dev,
gdev->ddr_paddr);
}
if (gdev->sram_vaddr)
- sram_free(gdev->sram_vaddr, sram_pool_sz);
+ gen_pool_free(gdev->sram_pool,
+ gdev->sram_vaddr,
+ sram_pool_sz);
kfree(gdev->info);
clk_put(gdev->pruss_clk);
kfree(gdev);
@@ -152,10 +155,17 @@ static int __devinit pruss_probe(struct platform_device *dev)
goto out_free;
}
- gdev->sram_vaddr = sram_alloc(sram_pool_sz, &(gdev->sram_paddr));
- if (!gdev->sram_vaddr) {
- dev_err(&dev->dev, "Could not allocate SRAM pool\n");
- goto out_free;
+ if (pdata->sram_pool) {
+ gdev->sram_pool = pdata->sram_pool;
+ gdev->sram_vaddr =
+ gen_pool_alloc(gdev->sram_pool, sram_pool_sz);
+ if (!gdev->sram_vaddr) {
+ dev_err(&dev->dev, "Could not allocate SRAM pool\n");
+ goto out_free;
+ }
+ gdev->sram_paddr =
+ gen_pool_virt_to_phys(gdev->sram_pool,
+ gdev->sram_vaddr);
}
gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz,
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1e741bca026..f034716190f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
irqreturn_t usb_hcd_irq (int irq, void *__hcd)
{
struct usb_hcd *hcd = __hcd;
+ unsigned long flags;
irqreturn_t rc;
+ /* IRQF_DISABLED doesn't work correctly with shared IRQs
+ * when the first handler doesn't use it. So let's just
+ * assume it's never used.
+ */
+ local_irq_save(flags);
+
if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
rc = IRQ_NONE;
else if (hcd->driver->irq(hcd) == IRQ_NONE)
@@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
else
rc = IRQ_HANDLED;
+ local_irq_restore(flags);
return rc;
}
EXPORT_SYMBOL_GPL(usb_hcd_irq);
@@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
int retval;
if (hcd->driver->irq) {
+
+ /* IRQF_DISABLED doesn't work as advertised when used together
+ * with IRQF_SHARED. As usb_hcd_irq() will always disable
+ * interrupts we can remove it here.
+ */
+ if (irqflags & IRQF_SHARED)
+ irqflags &= ~IRQF_DISABLED;
+
snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
hcd->driver->description, hcd->self.busnum);
retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index e426ad626d7..4bfa78af379 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -20,6 +20,7 @@
#include <linux/usb/ehci_def.h>
#include <linux/delay.h>
#include <linux/serial_core.h>
+#include <linux/kconfig.h>
#include <linux/kgdb.h>
#include <linux/kthread.h>
#include <asm/io.h>
@@ -614,12 +615,6 @@ err:
return -ENODEV;
}
-int dbgp_external_startup(struct usb_hcd *hcd)
-{
- return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
-}
-EXPORT_SYMBOL_GPL(dbgp_external_startup);
-
static int ehci_reset_port(int port)
{
u32 portsc;
@@ -979,6 +974,7 @@ struct console early_dbgp_console = {
.index = -1,
};
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD)
int dbgp_reset_prep(struct usb_hcd *hcd)
{
int ret = xen_dbgp_reset_prep(hcd);
@@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd)
}
EXPORT_SYMBOL_GPL(dbgp_reset_prep);
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+ return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
+EXPORT_SYMBOL_GPL(dbgp_external_startup);
+#endif /* USB_EHCI_HCD */
+
#ifdef CONFIG_KGDB
static char kgdbdbgp_buf[DBGP_MAX_PACKET];
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 2a4749c3eb3..23afa06b65a 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -44,7 +44,7 @@
#include <asm/unaligned.h>
#include <asm/mach-types.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <mach/usb.h>
@@ -61,6 +61,8 @@
#define DRIVER_DESC "OMAP UDC driver"
#define DRIVER_VERSION "4 October 2004"
+#define OMAP_DMA_USB_W2FC_TX0 29
+
/*
* The OMAP UDC needs _very_ early endpoint setup: before enabling the
* D+ pullup to allow enumeration. That's too early for the gadget
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 6458764994e..4ec3c0d7a18 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -20,6 +20,7 @@
#include <linux/ctype.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include "u_ether.h"
@@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
while (skb2) {
if (status < 0
|| ETH_HLEN > skb2->len
- || skb2->len > ETH_FRAME_LEN) {
+ || skb2->len > VLAN_ETH_FRAME_LEN) {
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
DBG(dev, "rx length %d\n", skb2->len);
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
index ca759652626..aa0f328922d 100644
--- a/drivers/usb/host/ehci-ls1x.c
+++ b/drivers/usb/host/ehci-ls1x.c
@@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
goto err_put_hcd;
}
- ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (ret)
goto err_put_hcd;
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 4a08fc0b27c..8e58a5fa199 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -24,7 +24,6 @@
#include <linux/usb/ulpi.h>
#include <linux/slab.h>
-#include <mach/hardware.h>
#include <linux/platform_data/usb-ehci-mxc.h>
#include <asm/mach-types.h>
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index d7fe287d067..0d5ac36fdf4 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -39,12 +39,13 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/usb/ulpi.h>
-#include <plat/usb.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/gpio.h>
#include <linux/clk.h>
+#include <linux/platform_data/usb-omap.h>
+
/* EHCI Register Set */
#define EHCI_INSNREG04 (0xA0)
#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 9c2717d6673..e7e8275028d 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -14,6 +14,9 @@
#include <linux/mbus.h>
#include <linux/clk.h>
#include <linux/platform_data/usb-ehci-orion.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
@@ -181,6 +184,8 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
}
}
+static u64 ehci_orion_dma_mask = DMA_BIT_MASK(32);
+
static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
{
struct orion_ehci_data *pd = pdev->dev.platform_data;
@@ -191,13 +196,17 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
struct clk *clk;
void __iomem *regs;
int irq, err;
+ enum orion_ehci_phy_ver phy_version;
if (usb_disabled())
return -ENODEV;
pr_debug("Initializing Orion-SoC USB Host Controller\n");
- irq = platform_get_irq(pdev, 0);
+ if (pdev->dev.of_node)
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ else
+ irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(&pdev->dev,
"Found HC with no IRQ. Check %s setup!\n",
@@ -215,6 +224,14 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
goto err1;
}
+ /*
+ * Right now device-tree probed devices don't get dma_mask
+ * set. Since shared usb code relies on it, set it here for
+ * now. Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &ehci_orion_dma_mask;
+
if (!request_mem_region(res->start, resource_size(res),
ehci_orion_hc_driver.description)) {
dev_dbg(&pdev->dev, "controller already in use\n");
@@ -262,7 +279,12 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
/*
* setup Orion USB controller.
*/
- switch (pd->phy_version) {
+ if (pdev->dev.of_node)
+ phy_version = EHCI_PHY_NA;
+ else
+ phy_version = pd->phy_version;
+
+ switch (phy_version) {
case EHCI_PHY_NA: /* dont change USB phy settings */
break;
case EHCI_PHY_ORION:
@@ -317,9 +339,19 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
MODULE_ALIAS("platform:orion-ehci");
+static const struct of_device_id ehci_orion_dt_ids[] __devinitdata = {
+ { .compatible = "marvell,orion-ehci", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
+
static struct platform_driver ehci_orion_driver = {
.probe = ehci_orion_drv_probe,
.remove = __exit_p(ehci_orion_drv_remove),
.shutdown = usb_hcd_platform_shutdown,
- .driver.name = "orion-ehci",
+ .driver = {
+ .name = "orion-ehci",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ehci_orion_dt_ids),
+ },
};
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 6223d175784..2de089001ae 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -28,7 +28,10 @@
#include <linux/pm_runtime.h>
#include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE 0xC5000000
+#define TEGRA_USB2_BASE 0xC5004000
+#define TEGRA_USB3_BASE 0xC5008000
#define TEGRA_USB_DMA_ALIGN 32
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 4531d03503c..439e6e4f2d6 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -25,7 +25,6 @@
#include <asm/mach-types.h>
#include <mach/mux.h>
-#include <plat/fpga.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -93,14 +92,14 @@ static int omap_ohci_transceiver_power(int on)
{
if (on) {
if (machine_is_omap_innovator() && cpu_is_omap1510())
- fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
+ __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
| ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
INNOVATOR_FPGA_CAM_USB_CONTROL);
else if (machine_is_omap_osk())
tps65010_set_gpio_out_value(GPIO1, LOW);
} else {
if (machine_is_omap_innovator() && cpu_is_omap1510())
- fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
+ __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
& ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
INNOVATOR_FPGA_CAM_USB_CONTROL);
else if (machine_is_omap_osk())
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 1b8133b6e45..bd7803dce9b 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -30,7 +30,6 @@
*/
#include <linux/platform_device.h>
-#include <plat/usb.h>
#include <linux/pm_runtime.h>
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c
index 84201cd1a47..41e378f17c6 100644
--- a/drivers/usb/host/ohci-xls.c
+++ b/drivers/usb/host/ohci-xls.c
@@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver,
goto err3;
}
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (retval != 0)
goto err4;
return retval;
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index c964d6af178..a87cdd2387c 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -34,8 +34,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/nop-usb-xceiv.h>
-
-#include <plat/usb.h>
+#include <linux/platform_data/usb-omap.h>
#include "musb_core.h"
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index ff5f112053d..aa34f22181c 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -38,13 +38,12 @@
#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/platform_data/usb-omap.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
-#include <plat/usb.h>
-
#include "musb_core.h"
#ifdef CONFIG_OF
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index d0b87e7b4ab..b6b84dacc79 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req)
fifo_count = musb_readw(epio, MUSB_RXCOUNT);
/*
- * use mode 1 only if we expect data of at least ep packet_sz
- * and have not yet received a short packet
+ * Enable Mode 1 on RX transfers only when short_not_ok flag
+ * is set. Currently short_not_ok flag is set only from
+ * file_storage and f_mass_storage drivers
*/
- if ((request->length - request->actual >= musb_ep->packet_sz) &&
- (fifo_count >= musb_ep->packet_sz))
+
+ if (request->short_not_ok && fifo_count == musb_ep->packet_sz)
use_mode_1 = 1;
else
use_mode_1 = 0;
@@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req)
c = musb->dma_controller;
channel = musb_ep->dma;
+ /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+ * mode 0 only. So we do not get endpoint interrupts due to DMA
+ * completion. We only get interrupts from DMA controller.
+ *
+ * We could operate in DMA mode 1 if we knew the size of the tranfer
+ * in advance. For mass storage class, request->length = what the host
+ * sends, so that'd work. But for pretty much everything else,
+ * request->length is routinely more than what the host sends. For
+ * most these gadgets, end of is signified either by a short packet,
+ * or filling the last byte of the buffer. (Sending extra data in
+ * that last pckate should trigger an overflow fault.) But in mode 1,
+ * we don't get DMA completion interrupt for short packets.
+ *
+ * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+ * to get endpoint interrupt on every DMA req, but that didn't seem
+ * to work reliably.
+ *
+ * REVISIT an updated g_file_storage can set req->short_not_ok, which
+ * then becomes usable as a runtime "use mode 1" hint...
+ */
+
/* Experimental: Mode1 works with mass storage use cases */
if (use_mode_1) {
csr |= MUSB_RXCSR_AUTOCLEAR;
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
index b85f3973e78..8ef656659fc 100644
--- a/drivers/usb/musb/omap2430.h
+++ b/drivers/usb/musb/omap2430.h
@@ -10,7 +10,7 @@
#ifndef __MUSB_OMAP243X_H__
#define __MUSB_OMAP243X_H__
-#include <plat/usb.h>
+#include <linux/platform_data/usb-omap.h>
/*
* OMAP2430-specific definitions
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 7a62b95dac2..bfca114f7c5 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include "musb_core.h"
#include "tusb6010.h"
@@ -25,6 +25,13 @@
#define MAX_DMAREQ 5 /* REVISIT: Really 6, but req5 not OK */
+#define OMAP24XX_DMA_EXT_DMAREQ0 2
+#define OMAP24XX_DMA_EXT_DMAREQ1 3
+#define OMAP242X_DMA_EXT_DMAREQ2 14
+#define OMAP242X_DMA_EXT_DMAREQ3 15
+#define OMAP242X_DMA_EXT_DMAREQ4 16
+#define OMAP242X_DMA_EXT_DMAREQ5 64
+
struct tusb_omap_dma_ch {
struct musb *musb;
void __iomem *tbase;
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index d62a91fedc2..0e62f504410 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev)
struct platform_device *musb;
struct ux500_glue *glue;
struct clk *clk;
-
+ int musbid;
int ret = -ENOMEM;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index d8c8a42bff3..6223062d5d1 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT
config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
- depends on TWL4030_CORE && REGULATOR_TWL4030
+ depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
select USB_OTG_UTILS
help
Enable this to support the USB OTG transceiver on TWL4030
@@ -68,7 +68,7 @@ config TWL4030_USB
config TWL6030_USB
tristate "TWL6030 USB Transceiver Driver"
- depends on TWL4030_CORE && OMAP_USB2
+ depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
select USB_OTG_UTILS
help
Enable this to support the USB OTG transceiver on TWL6030
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c
index 987116f9efc..9d13c81754e 100644
--- a/drivers/usb/phy/tegra_usb_phy.c
+++ b/drivers/usb/phy/tegra_usb_phy.c
@@ -29,7 +29,9 @@
#include <linux/usb/ulpi.h>
#include <asm/mach-types.h>
#include <linux/usb/tegra_usb_phy.h>
-#include <mach/iomap.h>
+
+#define TEGRA_USB_BASE 0xC5000000
+#define TEGRA_USB_SIZE SZ_16K
#define ULPI_VIEWPORT 0x170
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 7179b0c5f81..cff8dd5b462 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -2430,7 +2430,7 @@ static void keyspan_release(struct usb_serial *serial)
static int keyspan_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
- struct keyspan_port_private *s_priv;
+ struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
struct callbacks *cback;
@@ -2445,7 +2445,6 @@ static int keyspan_port_probe(struct usb_serial_port *port)
if (!p_priv)
return -ENOMEM;
- s_priv = usb_get_serial_data(port->serial);
p_priv->device_details = d_details;
/* Setup values for the various callback routines */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5dee7d61241..edc64bb6f45 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -158,6 +158,7 @@ static void option_instat_callback(struct urb *urb);
#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001
+#define NOVATELWIRELESS_PRODUCT_E362 0x9010
#define NOVATELWIRELESS_PRODUCT_G1 0xA001
#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
@@ -193,6 +194,9 @@ static void option_instat_callback(struct urb *urb);
#define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181
#define DELL_PRODUCT_5730_MINICARD_VZW 0x8182
+#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */
+
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
#define KYOCERA_PRODUCT_KPC680 0x180a
@@ -283,6 +287,7 @@ static void option_instat_callback(struct urb *urb);
/* ALCATEL PRODUCTS */
#define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S_X200 0x0000
+#define ALCATEL_PRODUCT_X220_X500D 0x0017
#define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002
@@ -706,6 +711,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
/* Novatel Ovation MC551 a.k.a. Verizon USB551L */
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -728,6 +734,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
@@ -1157,6 +1165,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
.driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
},
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 61a73ad1a18..a3e9c095f0d 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -455,9 +455,6 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
struct usb_serial *serial = port->serial;
struct urb *urb;
- if (endpoint == -1)
- return NULL; /* endpoint not needed */
-
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (urb == NULL) {
dev_dbg(&serial->interface->dev,
@@ -489,6 +486,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
init_usb_anchor(&portdata->delayed);
for (i = 0; i < N_IN_URB; i++) {
+ if (!port->bulk_in_size)
+ break;
+
buffer = (u8 *)__get_free_page(GFP_KERNEL);
if (!buffer)
goto bail_out_error;
@@ -502,8 +502,8 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
}
for (i = 0; i < N_OUT_URB; i++) {
- if (port->bulk_out_endpointAddress == -1)
- continue;
+ if (!port->bulk_out_size)
+ break;
buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
if (!buffer)
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index cf2688de083..e501dbc966b 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -33,7 +33,6 @@
#include <linux/math64.h>
#include <linux/platform_data/video-imxfb.h>
-#include <mach/hardware.h>
/*
* Complain if VAR is out of range.
@@ -53,8 +52,8 @@
#define LCDC_SIZE 0x04
#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20)
-#define YMAX_MASK (cpu_is_mx1() ? 0x1ff : 0x3ff)
-#define SIZE_YMAX(y) ((y) & YMAX_MASK)
+#define YMAX_MASK_IMX1 0x1ff
+#define YMAX_MASK_IMX21 0x3ff
#define LCDC_VPW 0x08
#define VPW_VPW(x) ((x) & 0x3ff)
@@ -128,12 +127,18 @@ struct imxfb_rgb {
struct fb_bitfield transp;
};
+enum imxfb_type {
+ IMX1_FB,
+ IMX21_FB,
+};
+
struct imxfb_info {
struct platform_device *pdev;
void __iomem *regs;
struct clk *clk_ipg;
struct clk *clk_ahb;
struct clk *clk_per;
+ enum imxfb_type devtype;
/*
* These are the addresses we mapped
@@ -168,6 +173,24 @@ struct imxfb_info {
void (*backlight_power)(int);
};
+static struct platform_device_id imxfb_devtype[] = {
+ {
+ .name = "imx1-fb",
+ .driver_data = IMX1_FB,
+ }, {
+ .name = "imx21-fb",
+ .driver_data = IMX21_FB,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imxfb_devtype);
+
+static inline int is_imx1_fb(struct imxfb_info *fbi)
+{
+ return fbi->devtype == IMX1_FB;
+}
+
#define IMX_NAME "IMX"
/*
@@ -366,7 +389,7 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
case 16:
default:
- if (cpu_is_mx1())
+ if (is_imx1_fb(fbi))
pcr |= PCR_BPIX_12;
else
pcr |= PCR_BPIX_16;
@@ -596,6 +619,7 @@ static struct fb_ops imxfb_ops = {
static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct imxfb_info *fbi = info->par;
+ u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21;
pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
var->xres, var->hsync_len,
@@ -617,7 +641,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
if (var->right_margin > 255)
printk(KERN_ERR "%s: invalid right_margin %d\n",
info->fix.id, var->right_margin);
- if (var->yres < 1 || var->yres > YMAX_MASK)
+ if (var->yres < 1 || var->yres > ymax_mask)
printk(KERN_ERR "%s: invalid yres %d\n",
info->fix.id, var->yres);
if (var->vsync_len > 100)
@@ -645,7 +669,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
VCR_V_WAIT_2(var->upper_margin),
fbi->regs + LCDC_VCR);
- writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
+ writel(SIZE_XMAX(var->xres) | (var->yres & ymax_mask),
fbi->regs + LCDC_SIZE);
writel(fbi->pcr, fbi->regs + LCDC_PCR);
@@ -765,6 +789,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
return -ENOMEM;
fbi = info->par;
+ fbi->devtype = pdev->id_entry->driver_data;
if (!fb_mode)
fb_mode = pdata->mode[0].mode.name;
@@ -939,6 +964,7 @@ static struct platform_driver imxfb_driver = {
.driver = {
.name = DRIVER_NAME,
},
+ .id_table = imxfb_devtype,
};
static int imxfb_setup(void)
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index ce1d452464e..73688720857 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -26,10 +26,9 @@
#include <linux/console.h>
#include <linux/clk.h>
#include <linux/mutex.h>
+#include <linux/dma/ipu-dma.h>
#include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
-#include <mach/ipu.h>
#include <linux/platform_data/video-mx3fb.h>
#include <asm/io.h>
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index b38b1dd15ce..2ee423279e3 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -23,7 +23,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <plat/fpga.h>
+#include <mach/hardware.h>
+
#include "omapfb.h"
static int innovator1510_panel_init(struct lcd_panel *panel,
@@ -38,13 +39,13 @@ static void innovator1510_panel_cleanup(struct lcd_panel *panel)
static int innovator1510_panel_enable(struct lcd_panel *panel)
{
- fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+ __raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
return 0;
}
static void innovator1510_panel_disable(struct lcd_panel *panel)
{
- fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+ __raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
}
static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 7767338f8b1..c39d6e46f8c 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -31,7 +31,7 @@
#include <linux/gfp.h>
#include <mach/lcdc.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <asm/mach-types.h>
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 4351c438b76..1b5ee8ec192 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -30,7 +30,7 @@
#include <linux/uaccess.h>
#include <linux/module.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index f79c137753d..c510a445739 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -25,7 +25,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b2af72dc20b..d94ef9e31a3 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -237,7 +237,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
core.pdev = pdev;
- dss_features_init();
+ dss_features_init(pdata->version);
dss_apply_init();
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b43477a5fae..a5ab354f267 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -37,8 +37,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <plat/cpu.h>
-
#include <video/omapdss.h>
#include "dss.h"
@@ -4042,29 +4040,44 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
.gfx_fifo_workaround = true,
};
-static int __init dispc_init_features(struct device *dev)
+static int __init dispc_init_features(struct platform_device *pdev)
{
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const struct dispc_features *src;
struct dispc_features *dst;
- dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (!dst) {
- dev_err(dev, "Failed to allocate DISPC Features\n");
+ dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
return -ENOMEM;
}
- if (cpu_is_omap24xx()) {
+ switch (pdata->version) {
+ case OMAPDSS_VER_OMAP24xx:
src = &omap24xx_dispc_feats;
- } else if (cpu_is_omap34xx()) {
- if (omap_rev() < OMAP3430_REV_ES3_0)
- src = &omap34xx_rev1_0_dispc_feats;
- else
- src = &omap34xx_rev3_0_dispc_feats;
- } else if (cpu_is_omap44xx()) {
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ src = &omap34xx_rev1_0_dispc_feats;
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ case OMAPDSS_VER_OMAP3630:
+ case OMAPDSS_VER_AM35xx:
+ src = &omap34xx_rev3_0_dispc_feats;
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
src = &omap44xx_dispc_feats;
- } else if (soc_is_omap54xx()) {
+ break;
+
+ case OMAPDSS_VER_OMAP5:
src = &omap44xx_dispc_feats;
- } else {
+ break;
+
+ default:
return -ENODEV;
}
@@ -4084,7 +4097,7 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
dispc.pdev = pdev;
- r = dispc_init_features(&dispc.pdev->dev);
+ r = dispc_init_features(dispc.pdev);
if (r)
return r;
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 2ab1c3e9655..363852a0f76 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -35,8 +35,6 @@
#include <video/omapdss.h>
-#include <plat/cpu.h>
-
#include "dss.h"
#include "dss_features.h"
@@ -792,29 +790,46 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
.dpi_select_source = &dss_dpi_select_source_omap5,
};
-static int __init dss_init_features(struct device *dev)
+static int __init dss_init_features(struct platform_device *pdev)
{
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const struct dss_features *src;
struct dss_features *dst;
- dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (!dst) {
- dev_err(dev, "Failed to allocate local DSS Features\n");
+ dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
return -ENOMEM;
}
- if (cpu_is_omap24xx())
+ switch (pdata->version) {
+ case OMAPDSS_VER_OMAP24xx:
src = &omap24xx_dss_feats;
- else if (cpu_is_omap34xx())
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ case OMAPDSS_VER_AM35xx:
src = &omap34xx_dss_feats;
- else if (cpu_is_omap3630())
+ break;
+
+ case OMAPDSS_VER_OMAP3630:
src = &omap3630_dss_feats;
- else if (cpu_is_omap44xx())
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
src = &omap44xx_dss_feats;
- else if (soc_is_omap54xx())
+ break;
+
+ case OMAPDSS_VER_OMAP5:
src = &omap54xx_dss_feats;
- else
+ break;
+
+ default:
return -ENODEV;
+ }
memcpy(dst, src, sizeof(*dst));
dss.feat = dst;
@@ -831,7 +846,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
dss.pdev = pdev;
- r = dss_init_features(&dss.pdev->dev);
+ r = dss_init_features(dss.pdev);
if (r)
return r;
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index acbc1e1efba..3e8287c8709 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -23,7 +23,6 @@
#include <linux/slab.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
#include "dss.h"
#include "dss_features.h"
@@ -825,10 +824,20 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
};
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+ enum omapdss_version version)
{
- if (cpu_is_omap44xx())
+ switch (version) {
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
ip_data->ops = &omap4_hdmi_functions;
+ break;
+ default:
+ ip_data->ops = NULL;
+ }
+
+ WARN_ON(ip_data->ops == NULL);
}
#endif
@@ -929,29 +938,44 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
return omap_current_dss_features->supported_rotation_types & rot_type;
}
-void dss_features_init(void)
+void dss_features_init(enum omapdss_version version)
{
- if (cpu_is_omap24xx())
+ switch (version) {
+ case OMAPDSS_VER_OMAP24xx:
omap_current_dss_features = &omap2_dss_features;
- else if (cpu_is_omap3630())
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ omap_current_dss_features = &omap3430_dss_features;
+ break;
+
+ case OMAPDSS_VER_OMAP3630:
omap_current_dss_features = &omap3630_dss_features;
- else if (cpu_is_omap34xx()) {
- if (soc_is_am35xx()) {
- omap_current_dss_features = &am35xx_dss_features;
- } else {
- omap_current_dss_features = &omap3430_dss_features;
- }
- }
- else if (omap_rev() == OMAP4430_REV_ES1_0)
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
omap_current_dss_features = &omap4430_es1_0_dss_features;
- else if (omap_rev() == OMAP4430_REV_ES2_0 ||
- omap_rev() == OMAP4430_REV_ES2_1 ||
- omap_rev() == OMAP4430_REV_ES2_2)
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES2:
omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
- else if (cpu_is_omap44xx())
+ break;
+
+ case OMAPDSS_VER_OMAP4:
omap_current_dss_features = &omap4_dss_features;
- else if (soc_is_omap54xx())
+ break;
+
+ case OMAPDSS_VER_OMAP5:
omap_current_dss_features = &omap5_dss_features;
- else
+ break;
+
+ case OMAPDSS_VER_AM35xx:
+ omap_current_dss_features = &am35xx_dss_features;
+ break;
+
+ default:
DSSWARN("Unsupported OMAP version");
+ break;
+ }
}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 9218113b5e8..fc492ef72a5 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -123,8 +123,9 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
bool dss_has_feature(enum dss_feat_id id);
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
-void dss_features_init(void);
+void dss_features_init(enum omapdss_version version);
#if defined(CONFIG_OMAP4_DSS_HDMI)
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+ enum omapdss_version version);
#endif
#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index a48a7dd75b3..adcc906d12f 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -323,6 +323,7 @@ static void hdmi_runtime_put(void)
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
{
+ struct omap_dss_board_info *pdata = hdmi.pdev->dev.platform_data;
int r;
struct gpio gpios[] = {
@@ -333,7 +334,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
DSSDBG("init_display\n");
- dss_init_hdmi_ip_ops(&hdmi.ip_data);
+ dss_init_hdmi_ip_ops(&hdmi.ip_data, pdata->version);
if (hdmi.vdda_hdmi_dac_reg == NULL) {
struct regulator *reg;
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 606b89f1235..55a39be694a 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -30,7 +30,7 @@
#include <linux/export.h>
#include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include <plat/vram.h>
#include "omapfb.h"
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 16db1589bd9..bc225e46fdd 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -31,9 +31,8 @@
#include <linux/omapfb.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
#include <plat/vram.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include "omapfb.h"
@@ -2396,10 +2395,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
goto err0;
}
- /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
- * available for OMAP2 and OMAP3
- */
- if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+ if (def_vrfb && !omap_vrfb_supported()) {
def_vrfb = 0;
dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
"ignoring the module parameter vrfb=y\n");
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index e8d8cc76a43..17aa174e187 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -30,7 +30,7 @@
#include <linux/omapfb.h>
#include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include "omapfb.h"
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 7e990220ad2..5d8fdac3b80 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,9 @@
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
-#include <plat/vrfb.h>
-#include <plat/sdrc.h>
+#include <video/omapvrfb.h>
#ifdef DEBUG
#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@
#define DBG(format, ...)
#endif
-#define SMS_ROT_VIRT_BASE(context, rot) \
- (((context >= 4) ? 0xD0000000 : 0x70000000) \
- + (0x4000000 * (context)) \
- + (0x1000000 * (rot)))
+#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context)
+#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context)
+#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot))
#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
@@ -53,10 +53,16 @@
#define SMS_PW_OFFSET 4
#define SMS_PS_OFFSET 0
-#define VRFB_NUM_CTXS 12
/* bitmap of reserved contexts */
static unsigned long ctx_map;
+struct vrfb_ctx {
+ u32 base;
+ u32 physical_ba;
+ u32 control;
+ u32 size;
+};
+
static DEFINE_MUTEX(ctx_lock);
/*
@@ -65,17 +71,34 @@ static DEFINE_MUTEX(ctx_lock);
* we don't need locking, since no drivers will run until after the wake-up
* has finished.
*/
-static struct {
- u32 physical_ba;
- u32 control;
- u32 size;
-} vrfb_hw_context[VRFB_NUM_CTXS];
+
+static void __iomem *vrfb_base;
+
+static int num_ctxs;
+static struct vrfb_ctx *ctxs;
+
+static bool vrfb_loaded;
+
+static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
+}
+
+static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
+}
+
+static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
+}
static inline void restore_hw_context(int ctx)
{
- omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
- omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
- omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
+ omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
+ omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
+ omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
}
static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
- vrfb_hw_context[ctx].physical_ba = paddr;
- vrfb_hw_context[ctx].size = size;
- vrfb_hw_context[ctx].control = control;
+ ctxs[ctx].physical_ba = paddr;
+ ctxs[ctx].size = size;
+ ctxs[ctx].control = control;
omap2_sms_write_rot_physical_ba(paddr, ctx);
omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
mutex_lock(&ctx_lock);
- for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+ for (ctx = 0; ctx < num_ctxs; ++ctx)
if ((ctx_map & (1 << ctx)) == 0)
break;
- if (ctx == VRFB_NUM_CTXS) {
+ if (ctx == num_ctxs) {
pr_err("vrfb: no free contexts\n");
r = -EBUSY;
goto out;
@@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
vrfb->context = ctx;
for (rot = 0; rot < 4; ++rot) {
- paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+ paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
pr_err("vrfb: failed to reserve VRFB "
"area for ctx %d, rotation %d\n",
@@ -314,3 +337,80 @@ out:
return r;
}
EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+bool omap_vrfb_supported(void)
+{
+ return vrfb_loaded;
+}
+EXPORT_SYMBOL(omap_vrfb_supported);
+
+static int __init vrfb_probe(struct platform_device *pdev)
+{
+ struct resource *mem;
+ int i;
+
+ /* first resource is the register res, the rest are vrfb contexts */
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "can't get vrfb base address\n");
+ return -EINVAL;
+ }
+
+ vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
+ if (!vrfb_base) {
+ dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
+ return -ENOMEM;
+ }
+
+ num_ctxs = pdev->num_resources - 1;
+
+ ctxs = devm_kzalloc(&pdev->dev,
+ sizeof(struct vrfb_ctx) * num_ctxs,
+ GFP_KERNEL);
+
+ if (!ctxs)
+ return -ENOMEM;
+
+ for (i = 0; i < num_ctxs; ++i) {
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+ if (!mem) {
+ dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
+ i);
+ return -EINVAL;
+ }
+
+ ctxs[i].base = mem->start;
+ }
+
+ vrfb_loaded = true;
+
+ return 0;
+}
+
+static void __exit vrfb_remove(struct platform_device *pdev)
+{
+ vrfb_loaded = false;
+}
+
+static struct platform_driver vrfb_driver = {
+ .driver.name = "omapvrfb",
+ .remove = __exit_p(vrfb_remove),
+};
+
+static int __init vrfb_init(void)
+{
+ return platform_driver_probe(&vrfb_driver, &vrfb_probe);
+}
+
+static void __exit vrfb_exit(void)
+{
+ platform_driver_unregister(&vrfb_driver);
+}
+
+module_init(vrfb_init);
+module_exit(vrfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("OMAP VRFB");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index b7f5173ff9e..917bb568168 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
case XenbusStateReconfiguring:
case XenbusStateReconfigured:
case XenbusStateUnknown:
- case XenbusStateClosed:
break;
case XenbusStateInitWait:
@@ -670,6 +669,10 @@ InitWait:
info->feature_resize = val;
break;
+ case XenbusStateClosed:
+ if (dev->state == XenbusStateClosed)
+ break;
+ /* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing:
xenbus_frontend_closed(dev);
break;
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 1e8659ca27e..809b0de59c0 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
void unregister_virtio_device(struct virtio_device *dev)
{
+ int index = dev->index; /* save for after device release */
+
device_unregister(&dev->dev);
- ida_simple_remove(&virtio_index_ida, dev->index);
+ ida_simple_remove(&virtio_index_ida, index);
}
EXPORT_SYMBOL_GPL(unregister_virtio_device);
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 05e1be85fde..dc42e44b6bc 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -32,6 +32,7 @@
#include <linux/timer.h>
#include <linux/bitops.h>
#include <linux/uaccess.h>
+#include <linux/of.h>
#include "at91sam9_wdt.h"
@@ -302,11 +303,21 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
return res;
}
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_wdt_dt_ids[] __initconst = {
+ { .compatible = "atmel,at91sam9260-wdt" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
+#endif
+
static struct platform_driver at91wdt_driver = {
.remove = __exit_p(at91wdt_remove),
.driver = {
.name = "at91_wdt",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91_wdt_dt_ids),
},
};
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index bcfab2b00ad..9a45d0294cf 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -33,7 +33,6 @@
#include <linux/uaccess.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
-#include <mach/hardware.h>
#define DRIVER_NAME "imx2-wdt"
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index f5db18dbc0f..477a1d47a64 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -46,8 +46,8 @@
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <mach/hardware.h>
-#include <plat/cpu.h>
-#include <plat/prcm.h>
+
+#include <linux/platform_data/omap-wd-timer.h>
#include "omap_wdt.h"
@@ -202,8 +202,10 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data,
static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ struct omap_wd_timer_platform_data *pdata;
struct omap_wdt_dev *wdev;
- int new_margin;
+ u32 rs;
+ int new_margin, bs;
static const struct watchdog_info ident = {
.identity = "OMAP Watchdog",
.options = WDIOF_SETTIMEOUT,
@@ -211,6 +213,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
};
wdev = file->private_data;
+ pdata = wdev->dev->platform_data;
switch (cmd) {
case WDIOC_GETSUPPORT:
@@ -219,17 +222,12 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
case WDIOC_GETSTATUS:
return put_user(0, (int __user *)arg);
case WDIOC_GETBOOTSTATUS:
-#ifdef CONFIG_ARCH_OMAP1
- if (cpu_is_omap16xx())
- return put_user(__raw_readw(ARM_SYSST),
- (int __user *)arg);
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
- if (cpu_is_omap24xx())
- return put_user(omap_prcm_get_reset_sources(),
- (int __user *)arg);
-#endif
- return put_user(0, (int __user *)arg);
+ if (!pdata || !pdata->read_reset_sources)
+ return put_user(0, (int __user *)arg);
+ rs = pdata->read_reset_sources();
+ bs = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ?
+ WDIOF_CARDRESET : 0;
+ return put_user(bs, (int __user *)arg);
case WDIOC_KEEPALIVE:
spin_lock(&wdt_lock);
omap_wdt_ping(wdev);
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 0e863703545..74354708c6c 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -2,6 +2,7 @@ ifneq ($(CONFIG_ARM),y)
obj-y += manage.o balloon.o
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
endif
+obj-$(CONFIG_X86) += fallback.o
obj-y += grant-table.o features.o events.o
obj-y += xenbus/
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 912ac81b6db..0be4df39e95 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1395,10 +1395,10 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
+ irq_enter();
#ifdef CONFIG_X86
exit_idle();
#endif
- irq_enter();
__xen_evtchn_do_upcall();
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c
new file mode 100644
index 00000000000..0ef7c4d40f8
--- /dev/null
+++ b/drivers/xen/fallback.c
@@ -0,0 +1,80 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <asm/hypervisor.h>
+#include <asm/xen/hypercall.h>
+
+int xen_event_channel_op_compat(int cmd, void *arg)
+{
+ struct evtchn_op op;
+ int rc;
+
+ op.cmd = cmd;
+ memcpy(&op.u, arg, sizeof(op.u));
+ rc = _hypercall1(int, event_channel_op_compat, &op);
+
+ switch (cmd) {
+ case EVTCHNOP_close:
+ case EVTCHNOP_send:
+ case EVTCHNOP_bind_vcpu:
+ case EVTCHNOP_unmask:
+ /* no output */
+ break;
+
+#define COPY_BACK(eop) \
+ case EVTCHNOP_##eop: \
+ memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \
+ break
+
+ COPY_BACK(bind_interdomain);
+ COPY_BACK(bind_virq);
+ COPY_BACK(bind_pirq);
+ COPY_BACK(status);
+ COPY_BACK(alloc_unbound);
+ COPY_BACK(bind_ipi);
+#undef COPY_BACK
+
+ default:
+ WARN_ON(rc != -ENOSYS);
+ break;
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
+
+int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
+{
+ struct physdev_op op;
+ int rc;
+
+ op.cmd = cmd;
+ memcpy(&op.u, arg, sizeof(op.u));
+ rc = _hypercall1(int, physdev_op_compat, &op);
+
+ switch (cmd) {
+ case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
+ case PHYSDEVOP_set_iopl:
+ case PHYSDEVOP_set_iobitmap:
+ case PHYSDEVOP_apic_write:
+ /* no output */
+ break;
+
+#define COPY_BACK(pop, fld) \
+ case PHYSDEVOP_##pop: \
+ memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \
+ break
+
+ COPY_BACK(irq_status_query, irq_status_query);
+ COPY_BACK(apic_read, apic_op);
+ COPY_BACK(ASSIGN_VECTOR, irq_op);
+#undef COPY_BACK
+
+ default:
+ WARN_ON(rc != -ENOSYS);
+ break;
+ }
+
+ return rc;
+}
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 610bfc6be17..2e22df2f7a3 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
#endif
}
+static void gntdev_free_map(struct grant_map *map)
+{
+ if (map == NULL)
+ return;
+
+ if (map->pages)
+ free_xenballooned_pages(map->count, map->pages);
+ kfree(map->pages);
+ kfree(map->grants);
+ kfree(map->map_ops);
+ kfree(map->unmap_ops);
+ kfree(map->kmap_ops);
+ kfree(map);
+}
+
static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
{
struct grant_map *add;
@@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
return add;
err:
- kfree(add->pages);
- kfree(add->grants);
- kfree(add->map_ops);
- kfree(add->unmap_ops);
- kfree(add->kmap_ops);
- kfree(add);
+ gntdev_free_map(add);
return NULL;
}
@@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)
evtchn_put(map->notify.event);
}
- if (map->pages) {
- if (!use_ptemod)
- unmap_grant_pages(map, 0, map->count);
-
- free_xenballooned_pages(map->count, map->pages);
- }
- kfree(map->pages);
- kfree(map->grants);
- kfree(map->map_ops);
- kfree(map->unmap_ops);
- kfree(map);
+ if (map->pages && !use_ptemod)
+ unmap_grant_pages(map, 0, map->count);
+ gntdev_free_map(map);
}
/* ------------------------------------------------------------------ */
diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index 89f76252a16..ac727028e65 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,
goto out;
/* Can't write a xenbus message larger we can buffer */
- if ((len + u->len) > sizeof(u->u.buffer)) {
+ if (len > sizeof(u->u.buffer) - u->len) {
/* On error, dump existing buffer */
u->len = 0;
rc = -EINVAL;