* Re: [BUG] radeon: suspend resume
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-07-14 20:13 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <CAG27Bk2NzdZELTeByjH5Sj_NbB+TOhYDK66aX1-9e=W_LT39Hg@mail.gmail.com>
On Jul 14, 2013, at 8:26 PM, Sami Kerola <kerolasa@iki.fi> wrote:
> Hello,
>
> I build from Linus's tree from point
>
> commit 9903883f1dd6e86f286b7bfa6e4b423f98c1cd9e
>
> a kernel which has a power management suspend/resume problem. In short I
> do not get video back at resume, and my laptop becomes completely
> unresponsive. I have hunch the NO_HZ has something to do with issue.
You will have to bisect and found the commit that introduce the bug
as commit 9903883f1dd6e86
Merge tag 'dm-3.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm
Pull device-mapper changes from Alasdair G Kergon:
"Add a device-mapper target called dm-switch to provide a multipath
framework for storage arrays that dynamically reconfigure their
preferred paths for different device regions.
Fix a bug in the verity target that prevented its use with some
specific sizes of devices.
Improve some locking mechanisms in the device-mapper core and bufio.
Add Mike Snitzer as a device-mapper maintainer.
A few more clean-ups and fixes"
is a merge about device-mapper not fbdev and even Radeon drivers
Best Regards,
J.
>
> # zgrep ^CONFIG_NO_HZ /proc/config.gz
> CONFIG_NO_HZ_COMMON=y
> CONFIG_NO_HZ_FULL=y
> CONFIG_NO_HZ=y
>
> The NO_HZ combined with this piece of hardware results seems to be the
> issue.
>
> 00:01.0 VGA compatible controller: Advanced Micro Devices, Inc.
> [AMD/ATI] Wrestler [Radeon HD 7310] (prog-if 00 [VGA controller])
> Subsystem: Toshiba America Info Systems Device fb33
> Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
> ParErr- Stepping- SERR- FastB2B- DisINTx+
> Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSELúst >TAbort-
> <TAbort- <MAbort- >SERR- <PERR- INTx-
> Latency: 0, Cache Line Size: 64 bytes
> Interrupt: pin A routed to IRQ 49
> Region 0: Memory at e0000000 (32-bit, prefetchable) [size%6M]
> Region 1: I/O ports at 5000 [size%6]
> Region 2: Memory at f0400000 (32-bit, non-prefetchable) [size%6K]
> Expansion ROM at <unassigned> [disabled]
> Capabilities: [50] Power Management version 3
> Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA
> PME(D0-,D1-,D2-,D3hot-,D3cold-)
> Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
> Capabilities: [58] Express (v2) Root Complex Integrated Endpoint, MSI 00
> DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s
> <4us, L1 unlimited
> ExtTag+ RBE+ FLReset-
> DevCtl: Report errors: Correctable- Non-Fatal- Fatal-
> Unsupported-
> RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
> MaxPayload 128 bytes, MaxReadReq 128 bytes
> DevSta: CorrErr- UncorrErr+ FatalErr- UnsuppReq+
> AuxPwr- TransPend-
> LnkCap: Port #0, Speed unknown, Width x0, ASPM
> unknown, Latency L0 <64ns, L1 <1us
> ClockPM- Surprise- LLActRep- BwNot-
> LnkCtl: ASPM Disabled; Disabled- Retrain- CommClk-
> ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
> LnkSta: Speed unknown, Width x0, TrErr- Train-
> SlotClk- DLActive- BWMgmt- ABWMgmt-
> DevCap2: Completion Timeout: Not Supported,
> TimeoutDis-, LTR-, OBFF Not Supported
> DevCtl2: Completion Timeout: 50us to 50ms,
> TimeoutDis-, LTR-, OBFF Disabled
> LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-
> Transmit Margin: Normal Operating Range,
> EnterModifiedCompliance- ComplianceSOS-
> Compliance De-emphasis: -6dB
> LnkSta2: Current De-emphasis Level: -6dB,
> EqualizationComplete-, EqualizationPhase1-
> EqualizationPhase2-, EqualizationPhase3-,
> LinkEqualizationRequest-
> Capabilities: [a0] MSI: Enable+ Count=1/1 Maskable- 64bit+
> Address: 00000000fee0300c Data: 4152
> Capabilities: [100 v1] Vendor Specific Information: ID\001
> Rev=1 Len\x010 <?>
> Kernel driver in use: radeon
> Kernel modules: radeon
>
>
> Here are some message from journalctl from the time suspend begun, and
> resume failed. To me the two lines with '*ERROR* radeon' does not look
> right. The messages are result of 'echo devices > /sys/power/pm_test'.
>
>
> Jul 14 12:51:12 kerolasa-home kernel: PM: Hibernation mode set to 'platform'
> Jul 14 12:51:12 kerolasa-home kernel: kobject: 'vcs63'
> (ffff8800d2c09010): kobject_add_internal: parent: 'vc', set: 'devices'
> Jul 14 12:51:12 kerolasa-home kernel: kobject: 'vcs63'
> (ffff8800d2c09010): kobject_uevent_env
> Jul 14 12:51:12 kerolasa-home kernel: kobject: 'vcs63'
> (ffff8800d2c09010): fill_kobj_path: path = '/devices/virtual/vc/vcs63'
> Jul 14 12:51:12 kerolasa-home kernel: kobject: 'vcsa63'
> (ffff8800d2c08010): kobject_add_internal: parent: 'vc', set: 'devices'
> Jul 14 12:51:12 kerolasa-home kernel: kobject: 'vcsa63'
> (ffff8800d2c08010): kobject_uevent_env
> Jul 14 12:51:12 kerolasa-home kernel: kobject: 'vcsa63'
> (ffff8800d2c08010): fill_kobj_path: path > '/devices/virtual/vc/vcsa63'
> Jul 14 12:51:12 kerolasa-home kernel: PM: Marking nosave pages: [mem
> 0x0009f000-0x000fffff]
> Jul 14 12:51:12 kerolasa-home kernel: PM: Marking nosave pages: [mem
> 0xdf6bf000-0xdfbfefff]
> Jul 14 12:51:12 kerolasa-home kernel: PM: Marking nosave pages: [mem
> 0xdfc00000-0xffffffff]
> Jul 14 12:51:12 kerolasa-home kernel: PM: Basic memory bitmaps created
> Jul 14 12:51:31 kerolasa-home kernel: PM: Syncing filesystems ... done.
> Jul 14 12:51:31 kerolasa-home dhcpcd[451]: wlan0: carrier lost
> Jul 14 12:51:31 kerolasa-home dhcpcd[451]: wlan0: deleting host route
> to 192.168.1.2 via 127.0.0.1
> Jul 14 12:51:31 kerolasa-home dhcpcd[451]: wlan0: deleting route to
> 192.168.1.0/24
> Jul 14 12:51:31 kerolasa-home dhcpcd[451]: wlan0: deleting default
> route via 192.168.1.1
> Jul 14 12:51:31 kerolasa-home kernel: Freezing user space processes
> ... (elapsed 0.001 seconds) done.
> Jul 14 12:51:31 kerolasa-home kernel: PM: Preallocating image
> memory... done (allocated 187558 pages)
> Jul 14 12:51:31 kerolasa-home kernel: PM: Allocated 750232 kbytes in
> 0.32 seconds (2344.47 MB/s)
> Jul 14 12:51:31 kerolasa-home kernel: Freezing remaining freezable
> tasks ... (elapsed 0.001 seconds) done.
> Jul 14 12:51:31 kerolasa-home kernel: Suspending console(s) (use
> no_console_suspend to debug)
> Jul 14 12:51:31 kerolasa-home kernel: wlan0: deauthenticating from
> 20:f3:a3:39:74:56 by local choice (reason=3)
> Jul 14 12:51:31 kerolasa-home kernel: cfg80211: Calling CRDA to update
> world regulatory domain
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'regulatory.0'
> (ffff8800d98bc820): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'regulatory.0'
> (ffff8800d98bc820): fill_kobj_path: path > '/devices/platform/regulatory.0'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '50'
> (ffff8800d8c97888): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '50'
> (ffff8800d8c97888): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '50': free name
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c974d8): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c974d8): auto cleanup kobject_del
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c974d8): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c974d8): kset_release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs': free name
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '49'
> (ffff8800d8c97ac8): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '49'
> (ffff8800d8c97ac8): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '49': free name
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c97b98): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c97b98): auto cleanup kobject_del
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c97b98): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d8c97b98): kset_release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs': free name
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: fence
> driver on ring 5 use gpu addr 0x0000000000177118 and cpu addr
> 0xffffc90004ab2118
> Jul 14 12:51:31 kerolasa-home kernel: PM: freeze of devices complete
> after 631.979 msecs
> Jul 14 12:51:31 kerolasa-home kernel: hibernation debug: Waiting for 5 seconds.
> Jul 14 12:51:31 kerolasa-home kernel: usb usb1: root hub lost power or was reset
> Jul 14 12:51:31 kerolasa-home kernel: usb usb2: root hub lost power or was reset
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '43'
> (ffff880106a39dc8): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '43'
> (ffff880106a39dc8): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '43': free name
> Jul 14 12:51:31 kerolasa-home kernel: usb usb4: root hub lost power or was reset
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '44'
> (ffff880106a39d08): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '44'
> (ffff880106a39d08): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '44': free name
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '45'
> (ffff880106a39c48): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '45'
> (ffff880106a39c48): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '45': free name
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff880106a39b98): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff880106a39b98): auto cleanup kobject_del
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff880106a39b98): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff880106a39b98): kset_release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs': free name
> Jul 14 12:51:31 kerolasa-home kernel: usb usb5: root hub lost power or was reset
> Jul 14 12:51:31 kerolasa-home kernel: xhci_hcd 0000:00:10.0: irq 43
> for MSI/MSI-X
> Jul 14 12:51:31 kerolasa-home kernel: xhci_hcd 0000:00:10.0: irq 44
> for MSI/MSI-X
> Jul 14 12:51:31 kerolasa-home kernel: rtlwifi: wireless switch is on
> Jul 14 12:51:31 kerolasa-home kernel: xhci_hcd 0000:00:10.0: irq 45
> for MSI/MSI-X
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d9012118): kobject_add_internal: parent: '0000:00:10.0', set:
> '<NULL>'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d9012118): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d9012118): kobject_uevent_env: filter function caused the
> event to drop!
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '43'
> (ffff8800d90121c8): kobject_add_internal: parent: 'msi_irqs', set:
> 'msi_irqs'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '44'
> (ffff8800d9012e88): kobject_add_internal: parent: 'msi_irqs', set:
> 'msi_irqs'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '45'
> (ffff8800d9012c48): kobject_add_internal: parent: 'msi_irqs', set:
> 'msi_irqs'
> Jul 14 12:51:31 kerolasa-home kernel: [drm] PCIE GART of 512M enabled
> (table at 0x0000000000145000).
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: WB enabled
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: fence
> driver on ring 0 use gpu addr 0x0000000018000c00 and cpu addr
> 0xffff8800d98a2c00
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: fence
> driver on ring 3 use gpu addr 0x0000000018000c0c and cpu addr
> 0xffff8800d98a2c0c
> Jul 14 12:51:31 kerolasa-home kernel: snd_hda_intel 0000:00:14.2: irq
> 49 for MSI/MSI-X
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d92b5718): kobject_add_internal: parent: '0000:00:14.2', set:
> '<NULL>'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d92b5718): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff8800d92b5718): kobject_uevent_env: filter function caused the
> event to drop!
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '49'
> (ffff8800d92b5648): kobject_add_internal: parent: 'msi_irqs', set:
> 'msi_irqs'
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: fence
> driver on ring 5 use gpu addr 0x00000000007ca118 and cpu addr
> 0xffffc90005432118
> Jul 14 12:51:31 kerolasa-home kernel: snd_hda_intel 0000:00:01.1: irq
> 50 for MSI/MSI-X
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff880106a39658): kobject_add_internal: parent: '0000:00:01.1', set:
> '<NULL>'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff880106a39658): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'msi_irqs'
> (ffff880106a39658): kobject_uevent_env: filter function caused the
> event to drop!
> Jul 14 12:51:31 kerolasa-home kernel: kobject: '50'
> (ffff8800d9012a08): kobject_add_internal: parent: 'msi_irqs', set:
> 'msi_irqs'
> Jul 14 12:51:31 kerolasa-home kernel: [drm] ring test on 0 succeeded in 1 usecs
> Jul 14 12:51:31 kerolasa-home kernel: [drm] ring test on 3 succeeded in 1 usecs
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'radeon_bl0'
> (ffff8800da197198): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'radeon_bl0'
> (ffff8800da197198): fill_kobj_path: path > '/devices/pci0000:00/0000:00:01.0/drm/card0/card0-LVDS-1/radeon_bl0'
> Jul 14 12:51:31 kerolasa-home kernel: ACPI: \_SB_.PCI0:
> ACPI_NOTIFY_BUS_CHECK event: unsupported
> Jul 14 12:51:31 kerolasa-home kernel: ACPI: \_SB_.PCI0: Bus check
> notify on _handle_hotplug_event_root
> Jul 14 12:51:31 kerolasa-home kernel: [drm] ring test on 5 succeeded in 1 usecs
> Jul 14 12:51:31 kerolasa-home kernel: [drm] UVD initialized successfully.
> Jul 14 12:51:31 kerolasa-home kernel: [drm] ib test on ring 0
> succeeded in 0 usecs
> Jul 14 12:51:31 kerolasa-home kernel: [drm] ib test on ring 3
> succeeded in 1 usecs
> Jul 14 12:51:31 kerolasa-home kernel: usb 5-4: reset high-speed USB
> device number 3 using ehci-pci
> Jul 14 12:51:31 kerolasa-home kernel: ata1: SATA link up 3.0 Gbps
> (SStatus 123 SControl 300)
> Jul 14 12:51:31 kerolasa-home kernel: ata2: SATA link up 1.5 Gbps
> (SStatus 113 SControl 300)
> Jul 14 12:51:31 kerolasa-home kernel: ata2.00: configured for UDMA/100
> Jul 14 12:51:31 kerolasa-home kernel: ata1.00: configured for UDMA/100
> Jul 14 12:51:31 kerolasa-home kernel: sd 0:0:0:0: [sda] Starting disk
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: GPU lockup
> CP stall for more than 10000msec
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: GPU lockup
> (waiting for 0x0000000000000004 last fence id 0x0000000000000002)
> Jul 14 12:51:31 kerolasa-home kernel: [drm:r600_uvd_ib_test] *ERROR*
> radeon: fence wait failed (-35).
> Jul 14 12:51:31 kerolasa-home kernel: [drm:radeon_ib_ring_tests]
> *ERROR* radeon: failed testing IB on ring 5 (-35).
> Jul 14 12:51:31 kerolasa-home kernel: PM: restore of devices complete
> after 11949.096 msecs
> Jul 14 12:51:31 kerolasa-home kernel: PM: Image restored successfully.
> Jul 14 12:51:31 kerolasa-home kernel: Restarting tasks ... done.
> Jul 14 12:51:31 kerolasa-home kernel: PM: Basic memory bitmaps freed
> Jul 14 12:51:31 kerolasa-home kernel: video LNXVIDEO:00: Restoring
> backlight state
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'radeon_bl0'
> (ffff8800da197198): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'radeon_bl0'
> (ffff8800da197198): fill_kobj_path: path > '/devices/pci0000:00/0000:00:01.0/drm/card0/card0-LVDS-1/radeon_bl0'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800db3b6010): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800db3b6010): fill_kobj_path: path > '/devices/LNXSYSTM:00/device:00/PNP0A08:00/PNP0C0A:00/power_supply/BAT0'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'power_supply'
> (ffff880106aba8a0): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'power_supply'
> (ffff880106aba8a0): auto cleanup kobject_del
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'power_supply'
> (ffff880106aba8a0): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'power_supply': free name
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800db3b6010): kobject_cleanup
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800db3b6010): calling ktype release
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0': free name
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'power_supply'
> (ffff8800d924d180): kobject_add_internal: parent: 'PNP0C0A:00', set:
> '(null)'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800d2c0e010): kobject_add_internal: parent: 'power_supply', set:
> 'devices'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800d2c0e010): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800d2c0e010): fill_kobj_path: path > '/devices/LNXSYSTM:00/device:00/PNP0A08:00/PNP0C0A:00/power_supply/BAT0'
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800d2c0e010): kobject_uevent_env
> Jul 14 12:51:31 kerolasa-home kernel: kobject: 'BAT0'
> (ffff8800d2c0e010): fill_kobj_path: path > '/devices/LNXSYSTM:00/device:00/PNP0A08:00/PNP0C0A:00/power_supply/BAT0'
> Jul 14 12:51:31 kerolasa-home kernel: PM: Hibernation mode set to 'platform'
> Jul 14 12:51:31 kerolasa-home kernel: PM: Marking nosave pages: [mem
> 0x0009f000-0x000fffff]
> Jul 14 12:51:31 kerolasa-home kernel: PM: Marking nosave pages: [mem
> 0xdf6bf000-0xdfbfefff]
> Jul 14 12:51:31 kerolasa-home kernel: PM: Marking nosave pages: [mem
> 0xdfc00000-0xffffffff]
> Jul 14 12:51:31 kerolasa-home kernel: PM: Basic memory bitmaps created
> Jul 14 12:51:32 kerolasa-home kernel: wlan0: authenticate with 20:f3:a3:39:74:56
> Jul 14 12:51:32 kerolasa-home kernel: wlan0: send auth to
> 20:f3:a3:39:74:56 (try 1/3)
> Jul 14 12:51:32 kerolasa-home kernel: wlan0: authenticated
> Jul 14 12:51:32 kerolasa-home kernel: wlan0: associate with
> 20:f3:a3:39:74:56 (try 1/3)
> Jul 14 12:51:32 kerolasa-home kernel: wlan0: RX AssocResp from
> 20:f3:a3:39:74:56 (capab=0x411 status=0 aid=1)
> Jul 14 12:51:32 kerolasa-home kernel: wlan0: associated
> Jul 14 12:51:32 kerolasa-home dhcpcd[451]: wlan0: carrier acquired
>
> Let me know if more debug information or output is needed.
>
> --
> Sami Kerola
> http://www.iki.fi/kerolasa/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] video: nuc900fb: fix to pass correct device identity to free_irq()
From: Wan ZongShun @ 2013-07-15 2:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPgLHd_mMOOeMecVJbTQjiK+xJD+-8jvgH6oAFqTHK_uSpWOJw@mail.gmail.com>
2013/7/12 Wei Yongjun <weiyj.lk@gmail.com>:
> From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
>
> free_irq() expects the same device identity that was passed to
> corresponding request_irq(), otherwise the IRQ is not freed.
>
> Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Sorry, repost.
Hi Yongjun,
(1) ret = request_irq(irq, nuc900fb_irqhandler, 0,
pdev->name, fbinfo);
(2) static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id)
{
struct nuc900fb_info *fbi = dev_id;
void __iomem *regs = fbi->io;
From (1) and (2), we should consider the wrong with passing 'fbinfo'
to 'nuc900fb_irqhandler', it should pass the 'fbi' instead as
following codes:
ret = request_irq(irq, nuc900fb_irqhandler, 0,
pdev->name, fbi);
So if we fix this wrong,' free_irq(irq, fbi);' would be ok, right?
Thanks!
Vincent Wan.
> ---
> drivers/video/nuc900fb.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
> index 8c527e5..ebd5501 100644
> --- a/drivers/video/nuc900fb.c
> +++ b/drivers/video/nuc900fb.c
> @@ -661,7 +661,7 @@ release_clock:
> clk_disable(fbi->clk);
> clk_put(fbi->clk);
> release_irq:
> - free_irq(irq, fbi);
> + free_irq(irq, fbinfo);
> release_regs:
> iounmap(fbi->io);
> release_mem_region:
> @@ -702,7 +702,7 @@ static int nuc900fb_remove(struct platform_device *pdev)
> iounmap(fbi->io);
>
> irq = platform_get_irq(pdev, 0);
> - free_irq(irq, fbi);
> + free_irq(irq, fbinfo);
>
> release_resource(fbi->mem);
> kfree(fbi->mem);
>
--
Wan ZongShun.
www.mcuos.com
^ permalink raw reply
* [PATCH] video: remove unused variable "dev" in vga16fb_destroy()
From: Yijing Wang @ 2013-07-15 6:29 UTC (permalink / raw)
To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
Cc: linux-kernel, linux-fbdev, Hanjun Guo, jiang.liu, Yijing Wang,
Jingoo Han
Delete unused variable "dev" to fix build warning in
drivers/video/vga16fb.c
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
Cc: Jingoo Han <jg1.han@samsung.com>
---
drivers/video/vga16fb.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 830ded4..2827333 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1265,7 +1265,6 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
static void vga16fb_destroy(struct fb_info *info)
{
- struct platform_device *dev = container_of(info->device, struct platform_device, dev);
iounmap(info->screen_base);
fb_dealloc_cmap(&info->cmap);
/* XXX unshare VGA regions */
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] video: remove unused variable "dev" in vga16fb_destroy()
From: Jingoo Han @ 2013-07-15 7:13 UTC (permalink / raw)
To: 'Yijing Wang', 'Jean-Christophe Plagniol-Villard',
'Tomi Valkeinen'
Cc: linux-kernel, linux-fbdev, 'Hanjun Guo', jiang.liu,
Jingoo Han
In-Reply-To: <1373869765-52572-1-git-send-email-wangyijing@huawei.com>
On Monday, July 15, 2013 3:29 PM, Yijing Wang wrote:
>
> Delete unused variable "dev" to fix build warning in
> drivers/video/vga16fb.c
>
> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
> Cc: Jingoo Han <jg1.han@samsung.com>
It looks good.
Reviewed-by: Jingoo Han <jg1.han@samsung.com>
Best regards,
Jingoo Han
> ---
> drivers/video/vga16fb.c | 1 -
> 1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
> index 830ded4..2827333 100644
> --- a/drivers/video/vga16fb.c
> +++ b/drivers/video/vga16fb.c
> @@ -1265,7 +1265,6 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
>
> static void vga16fb_destroy(struct fb_info *info)
> {
> - struct platform_device *dev = container_of(info->device, struct platform_device, dev);
> iounmap(info->screen_base);
> fb_dealloc_cmap(&info->cmap);
> /* XXX unshare VGA regions */
> --
> 1.7.1
^ permalink raw reply
* Re: [BUG] radeon: suspend resume
From: Michel Dänzer @ 2013-07-15 10:35 UTC (permalink / raw)
To: kerolasa; +Cc: dri-devel
In-Reply-To: <CAG27Bk2NzdZELTeByjH5Sj_NbB+TOhYDK66aX1-9e=W_LT39Hg@mail.gmail.com>
[ The radeon driver is discussed on the dri-devel mailing list, moving
there ]
On Son, 2013-07-14 at 13:26 +0100, Sami Kerola wrote:
>
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: GPU lockup
> CP stall for more than 10000msec
> Jul 14 12:51:31 kerolasa-home kernel: radeon 0000:00:01.0: GPU lockup
> (waiting for 0x0000000000000004 last fence id 0x0000000000000002)
> Jul 14 12:51:31 kerolasa-home kernel: [drm:r600_uvd_ib_test] *ERROR*
> radeon: fence wait failed (-35).
> Jul 14 12:51:31 kerolasa-home kernel: [drm:radeon_ib_ring_tests]
> *ERROR* radeon: failed testing IB on ring 5 (-35).
Looks like the patch from
https://bugs.freedesktop.org/show_bug.cgi?idf425 might help.
--
Earthling Michel Dänzer | http://www.amd.com
Libre software enthusiast | Debian, X and DRI developer
^ permalink raw reply
* [PATCH 0/3] Few ignored framebuffer fixes/additions
From: Maxime Ripard @ 2013-07-15 15:26 UTC (permalink / raw)
To: linux-arm-kernel
Hi Andrew,
Sorry to bother you again with the framebuffer stuff but the new
maintainer doesn't appear to be responsive either.k
This is a collection of patches that have been silently ignored,
despite being pinged numerous times:
- Patch 1 has been sent for the first time on June 7 [1], resent on
June 18 [2], plus two pings on July, 3rd [3] and July, 12th [4]. With
no comments whatsoever.
- Patch 2 has been sent on June, 21st [5]. Jean Christophe commented
on it on June, 24th [6], but every attempts at getting clear
explanations on what was expected have been ignored ever since
(June 25th [7], July 12th [8])
- Patch 3 was sent on June 21st along with Patch 2 [9]. There was
comments on it and a second version was sent on June 24th
[10]. Without any comments so far.
Could you take a look at those patches? We already missed 3.11, and
I'd really like not to miss another merge window because of the fbdev
curse.
Thanks,
Maxime
[1]: https://lkml.org/lkml/2013/6/7/116
[2]: https://lkml.org/lkml/2013/6/18/130
[3]: https://lkml.org/lkml/2013/7/3/105
[4]: https://lkml.org/lkml/2013/7/12/177
[5]: https://lkml.org/lkml/2013/6/21/405
[6]: https://lkml.org/lkml/2013/6/24/313
[7]: https://lkml.org/lkml/2013/6/25/274
[8]: https://lkml.org/lkml/2013/7/12/103
[9]: https://lkml.org/lkml/2013/6/21/407
[10]: https://lkml.org/lkml/2013/6/24/302
Alexandre Belloni (1):
fb: backlight: HX8357: Add HX8369 support
Hector Palacios (1):
video: mxsfb: fix color settings for 18bit data bus and 32bpp
Maxime Ripard (1):
video: hx8357: Make IM pins optional
drivers/video/backlight/hx8357.c | 255 +++++++++++++++++++++++++++++++++------
drivers/video/mxsfb.c | 26 ----
2 files changed, 218 insertions(+), 63 deletions(-)
--
1.8.3.2
^ permalink raw reply
* [PATCH 1/3] video: mxsfb: fix color settings for 18bit data bus and 32bpp
From: Maxime Ripard @ 2013-07-15 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1373902022-20439-1-git-send-email-maxime.ripard@free-electrons.com>
From: Hector Palacios <hector.palacios@digi.com>
For a combination of 18bit LCD data bus width and a color
mode of 32bpp, the driver was setting the color mapping to
rgb666, which is wrong, as the color in memory realy has an
rgb888 layout.
This patch also removes the setting of flag CTRL_DF24 that
makes the driver dimiss the upper 2 bits when handling 32/24bpp
colors in a diplay with 18bit data bus width. This flag made
true color images display wrong in such configurations.
Finally, the color mapping rgb666 has also been removed as nobody
is using it and high level applications like Qt5 cannot work
with it either.
Reference: https://lkml.org/lkml/2013/5/23/220
Signed-off-by: Hector Palacios <hector.palacios@digi.com>
Acked-by: Juergen Beisert <jbe@pengutronix.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/video/mxsfb.c | 26 --------------------------
1 file changed, 26 deletions(-)
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 3ba3771..dc09ebe 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -239,24 +239,6 @@ static const struct fb_bitfield def_rgb565[] = {
}
};
-static const struct fb_bitfield def_rgb666[] = {
- [RED] = {
- .offset = 16,
- .length = 6,
- },
- [GREEN] = {
- .offset = 8,
- .length = 6,
- },
- [BLUE] = {
- .offset = 0,
- .length = 6,
- },
- [TRANSP] = { /* no support for transparency */
- .length = 0,
- }
-};
-
static const struct fb_bitfield def_rgb888[] = {
[RED] = {
.offset = 16,
@@ -309,9 +291,6 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
break;
case STMLCDIF_16BIT:
case STMLCDIF_18BIT:
- /* 24 bit to 18 bit mapping */
- rgb = def_rgb666;
- break;
case STMLCDIF_24BIT:
/* real 24 bit */
rgb = def_rgb888;
@@ -453,11 +432,6 @@ static int mxsfb_set_par(struct fb_info *fb_info)
return -EINVAL;
case STMLCDIF_16BIT:
case STMLCDIF_18BIT:
- /* 24 bit to 18 bit mapping */
- ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
- * each colour component
- */
- break;
case STMLCDIF_24BIT:
/* real 24 bit */
break;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/3] video: hx8357: Make IM pins optional
From: Maxime Ripard @ 2013-07-15 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1373902022-20439-1-git-send-email-maxime.ripard@free-electrons.com>
The IM pins of the HX8357 controller are used to define the interface
used to feed pixel stream to the LCD panel.
Most of the time, these pins are directly routed to either the ground or
the VCC to set their values.
Remove the need to assign GPIOs to these pins when we are in such a case.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/video/backlight/hx8357.c | 52 +++++++++++++++++++++++-----------------
1 file changed, 30 insertions(+), 22 deletions(-)
diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
index a0482b5..ed94796 100644
--- a/drivers/video/backlight/hx8357.c
+++ b/drivers/video/backlight/hx8357.c
@@ -76,6 +76,7 @@ struct hx8357_data {
unsigned reset;
struct spi_device *spi;
int state;
+ bool use_im_pins;
};
static u8 hx8357_seq_power[] = {
@@ -250,9 +251,11 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
* Set the interface selection pins to SPI mode, with three
* wires
*/
- gpio_set_value_cansleep(lcd->im_pins[0], 1);
- gpio_set_value_cansleep(lcd->im_pins[1], 0);
- gpio_set_value_cansleep(lcd->im_pins[2], 1);
+ if (lcd->use_im_pins) {
+ gpio_set_value_cansleep(lcd->im_pins[0], 1);
+ gpio_set_value_cansleep(lcd->im_pins[1], 0);
+ gpio_set_value_cansleep(lcd->im_pins[2], 1);
+ }
/* Reset the screen */
gpio_set_value(lcd->reset, 1);
@@ -424,26 +427,31 @@ static int hx8357_probe(struct spi_device *spi)
return -EINVAL;
}
- for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
- lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
- "im-gpios", i);
- if (lcd->im_pins[i] = -EPROBE_DEFER) {
- dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
- return -EPROBE_DEFER;
- }
- if (!gpio_is_valid(lcd->im_pins[i])) {
- dev_err(&spi->dev, "Missing dt property: im-gpios\n");
- return -EINVAL;
+ if (of_find_property(spi->dev.of_node, "im-gpios", NULL)) {
+ lcd->use_im_pins = 1;
+
+ for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
+ lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
+ "im-gpios", i);
+ if (lcd->im_pins[i] = -EPROBE_DEFER) {
+ dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
+ return -EPROBE_DEFER;
+ }
+ if (!gpio_is_valid(lcd->im_pins[i])) {
+ dev_err(&spi->dev, "Missing dt property: im-gpios\n");
+ return -EINVAL;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
+ GPIOF_OUT_INIT_LOW, "im_pins");
+ if (ret) {
+ dev_err(&spi->dev, "failed to request gpio %d: %d\n",
+ lcd->im_pins[i], ret);
+ return -EINVAL;
+ }
}
-
- ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
- GPIOF_OUT_INIT_LOW, "im_pins");
- if (ret) {
- dev_err(&spi->dev, "failed to request gpio %d: %d\n",
- lcd->im_pins[i], ret);
- return -EINVAL;
- }
- }
+ } else
+ lcd->use_im_pins = 0;
lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops);
if (IS_ERR(lcdev)) {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/3] fb: backlight: HX8357: Add HX8369 support
From: Maxime Ripard @ 2013-07-15 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1373902022-20439-1-git-send-email-maxime.ripard@free-electrons.com>
From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Add support for the Himax HX8369 controller as it is quite similar to the
hx8357.
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/video/backlight/hx8357.c | 203 ++++++++++++++++++++++++++++++++++++---
1 file changed, 188 insertions(+), 15 deletions(-)
diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
index ed94796..b035fab 100644
--- a/drivers/video/backlight/hx8357.c
+++ b/drivers/video/backlight/hx8357.c
@@ -71,6 +71,18 @@
#define HX8357_SET_POWER_NORMAL 0xd2
#define HX8357_SET_PANEL_RELATED 0xe9
+#define HX8369_SET_DISPLAY_BRIGHTNESS 0x51
+#define HX8369_WRITE_CABC_DISPLAY_VALUE 0x53
+#define HX8369_WRITE_CABC_BRIGHT_CTRL 0x55
+#define HX8369_WRITE_CABC_MIN_BRIGHTNESS 0x5e
+#define HX8369_SET_POWER 0xb1
+#define HX8369_SET_DISPLAY_MODE 0xb2
+#define HX8369_SET_DISPLAY_WAVEFORM_CYC 0xb4
+#define HX8369_SET_VCOM 0xb6
+#define HX8369_SET_EXTENSION_COMMAND 0xb9
+#define HX8369_SET_GIP 0xd5
+#define HX8369_SET_GAMMA_CURVE_RELATED 0xe0
+
struct hx8357_data {
unsigned im_pins[HX8357_NUM_IM_PINS];
unsigned reset;
@@ -144,6 +156,61 @@ static u8 hx8357_seq_display_mode[] = {
HX8357_SET_DISPLAY_MODE_RGB_INTERFACE,
};
+static u8 hx8369_seq_write_CABC_min_brightness[] = {
+ HX8369_WRITE_CABC_MIN_BRIGHTNESS, 0x00,
+};
+
+static u8 hx8369_seq_write_CABC_control[] = {
+ HX8369_WRITE_CABC_DISPLAY_VALUE, 0x24,
+};
+
+static u8 hx8369_seq_set_display_brightness[] = {
+ HX8369_SET_DISPLAY_BRIGHTNESS, 0xFF,
+};
+
+static u8 hx8369_seq_write_CABC_control_setting[] = {
+ HX8369_WRITE_CABC_BRIGHT_CTRL, 0x02,
+};
+
+static u8 hx8369_seq_extension_command[] = {
+ HX8369_SET_EXTENSION_COMMAND, 0xff, 0x83, 0x69,
+};
+
+static u8 hx8369_seq_display_related[] = {
+ HX8369_SET_DISPLAY_MODE, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x01,
+};
+
+static u8 hx8369_seq_panel_waveform_cycle[] = {
+ HX8369_SET_DISPLAY_WAVEFORM_CYC, 0x0a, 0x1d, 0x80, 0x06, 0x02,
+};
+
+static u8 hx8369_seq_set_address_mode[] = {
+ HX8357_SET_ADDRESS_MODE, 0x00,
+};
+
+static u8 hx8369_seq_vcom[] = {
+ HX8369_SET_VCOM, 0x3e, 0x3e,
+};
+
+static u8 hx8369_seq_gip[] = {
+ HX8369_SET_GIP, 0x00, 0x01, 0x03, 0x25, 0x01, 0x02, 0x28, 0x70,
+ 0x11, 0x13, 0x00, 0x00, 0x40, 0x26, 0x51, 0x37, 0x00, 0x00, 0x71,
+ 0x35, 0x60, 0x24, 0x07, 0x0f, 0x04, 0x04,
+};
+
+static u8 hx8369_seq_power[] = {
+ HX8369_SET_POWER, 0x01, 0x00, 0x34, 0x03, 0x00, 0x11, 0x11, 0x32,
+ 0x2f, 0x3f, 0x3f, 0x01, 0x3a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
+};
+
+static u8 hx8369_seq_gamma_curve_related[] = {
+ HX8369_SET_GAMMA_CURVE_RELATED, 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d,
+ 0x2e, 0x4a, 0x08, 0x0e, 0x0f, 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
+ 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, 0x2e, 0x4a, 0x08, 0x0e, 0x0f,
+ 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
+};
+
static int hx8357_spi_write_then_read(struct lcd_device *lcdev,
u8 *txbuf, u16 txlen,
u8 *rxbuf, u16 rxlen)
@@ -242,6 +309,18 @@ static int hx8357_exit_standby(struct lcd_device *lcdev)
return 0;
}
+static void hx8357_lcd_reset(struct lcd_device *lcdev)
+{
+ struct hx8357_data *lcd = lcd_get_data(lcdev);
+
+ gpio_set_value(lcd->reset, 1);
+ usleep_range(10000, 12000);
+ gpio_set_value(lcd->reset, 0);
+ usleep_range(10000, 12000);
+ gpio_set_value(lcd->reset, 1);
+ msleep(120);
+}
+
static int hx8357_lcd_init(struct lcd_device *lcdev)
{
struct hx8357_data *lcd = lcd_get_data(lcdev);
@@ -257,14 +336,6 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
gpio_set_value_cansleep(lcd->im_pins[2], 1);
}
- /* Reset the screen */
- gpio_set_value(lcd->reset, 1);
- usleep_range(10000, 12000);
- gpio_set_value(lcd->reset, 0);
- usleep_range(10000, 12000);
- gpio_set_value(lcd->reset, 1);
- msleep(120);
-
ret = hx8357_spi_write_array(lcdev, hx8357_seq_power,
ARRAY_SIZE(hx8357_seq_power));
if (ret < 0)
@@ -359,6 +430,94 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
return 0;
}
+static int hx8369_lcd_init(struct lcd_device *lcdev)
+{
+ int ret;
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_extension_command,
+ ARRAY_SIZE(hx8369_seq_extension_command));
+ if (ret < 0)
+ return ret;
+ usleep_range(10000, 12000);
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_display_related,
+ ARRAY_SIZE(hx8369_seq_display_related));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_panel_waveform_cycle,
+ ARRAY_SIZE(hx8369_seq_panel_waveform_cycle));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_address_mode,
+ ARRAY_SIZE(hx8369_seq_set_address_mode));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_vcom,
+ ARRAY_SIZE(hx8369_seq_vcom));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_gip,
+ ARRAY_SIZE(hx8369_seq_gip));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_power,
+ ARRAY_SIZE(hx8369_seq_power));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
+ if (ret < 0)
+ return ret;
+
+ msleep(120);
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_gamma_curve_related,
+ ARRAY_SIZE(hx8369_seq_gamma_curve_related));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
+ if (ret < 0)
+ return ret;
+ usleep_range(1000, 1200);
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_write_CABC_control,
+ ARRAY_SIZE(hx8369_seq_write_CABC_control));
+ if (ret < 0)
+ return ret;
+ usleep_range(10000, 12000);
+
+ ret = hx8357_spi_write_array(lcdev,
+ hx8369_seq_write_CABC_control_setting,
+ ARRAY_SIZE(hx8369_seq_write_CABC_control_setting));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_array(lcdev,
+ hx8369_seq_write_CABC_min_brightness,
+ ARRAY_SIZE(hx8369_seq_write_CABC_min_brightness));
+ if (ret < 0)
+ return ret;
+ usleep_range(10000, 12000);
+
+ ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_display_brightness,
+ ARRAY_SIZE(hx8369_seq_set_display_brightness));
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
+ if (ret < 0)
+ return ret;
+ msleep(100);
+
+ return 0;
+}
+
#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
static int hx8357_set_power(struct lcd_device *lcdev, int power)
@@ -391,10 +550,24 @@ static struct lcd_ops hx8357_ops = {
.get_power = hx8357_get_power,
};
+static const struct of_device_id hx8357_dt_ids[] = {
+ {
+ .compatible = "himax,hx8357",
+ .data = hx8357_lcd_init,
+ },
+ {
+ .compatible = "himax,hx8369",
+ .data = hx8369_lcd_init,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
+
static int hx8357_probe(struct spi_device *spi)
{
struct lcd_device *lcdev;
struct hx8357_data *lcd;
+ const struct of_device_id *match;
int i, ret;
lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
@@ -411,6 +584,10 @@ static int hx8357_probe(struct spi_device *spi)
lcd->spi = spi;
+ match = of_match_device(hx8357_dt_ids, &spi->dev);
+ if (!match || !match->data)
+ return -EINVAL;
+
lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0);
if (!gpio_is_valid(lcd->reset)) {
dev_err(&spi->dev, "Missing dt property: gpios-reset\n");
@@ -460,7 +637,9 @@ static int hx8357_probe(struct spi_device *spi)
}
spi_set_drvdata(spi, lcdev);
- ret = hx8357_lcd_init(lcdev);
+ hx8357_lcd_reset(lcdev);
+
+ ret = ((int (*)(struct lcd_device *))match->data)(lcdev);
if (ret) {
dev_err(&spi->dev, "Couldn't initialize panel\n");
goto init_error;
@@ -483,12 +662,6 @@ static int hx8357_remove(struct spi_device *spi)
return 0;
}
-static const struct of_device_id hx8357_dt_ids[] = {
- { .compatible = "himax,hx8357" },
- {},
-};
-MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
-
static struct spi_driver hx8357_driver = {
.probe = hx8357_probe,
.remove = hx8357_remove,
--
1.8.3.2
^ permalink raw reply related
* [PATCH RESEND] video: mxsfb: Let device core handle pinctrl
From: Fabio Estevam @ 2013-07-15 21:31 UTC (permalink / raw)
To: linux-fbdev
From: Fabio Estevam <fabio.estevam@freescale.com>
Since commit ab78029 (drivers/pinctrl: grab default handles from device core)
we can rely on device core for handling pinctrl, so remove
devm_pinctrl_get_select_default() from the driver.
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
---
Andrew,
Should this go via your tree?
drivers/video/mxsfb.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 21223d4..9d6a286 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -46,7 +46,6 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
-#include <linux/pinctrl/consumer.h>
#include <linux/fb.h>
#include <linux/regulator/consumer.h>
#include <video/of_display_timing.h>
@@ -877,7 +876,6 @@ static int mxsfb_probe(struct platform_device *pdev)
struct mxsfb_info *host;
struct fb_info *fb_info;
struct fb_modelist *modelist;
- struct pinctrl *pinctrl;
int ret;
if (of_id)
@@ -909,12 +907,6 @@ static int mxsfb_probe(struct platform_device *pdev)
host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
- pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
- if (IS_ERR(pinctrl)) {
- ret = PTR_ERR(pinctrl);
- goto fb_release;
- }
-
host->clk = devm_clk_get(&host->pdev->dev, NULL);
if (IS_ERR(host->clk)) {
ret = PTR_ERR(host->clk);
--
1.8.1.2
^ permalink raw reply related
* [PATCH] video: nuc900fb: fix to pass correct device identity to request_irq()
From: Wei Yongjun @ 2013-07-16 0:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPgLHd_mMOOeMecVJbTQjiK+xJD+-8jvgH6oAFqTHK_uSpWOJw@mail.gmail.com>
The IRQ handler nuc900fb_irqhandler() use dev_id as a type of
struct nuc900fb_info *, so we should pass fbi as the device
identity to request_irq().
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
---
Was 'video: nuc900fb: fix to pass correct device identity to free_irq()'
---
drivers/video/nuc900fb.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 8c527e5..796e511 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -587,8 +587,7 @@ static int nuc900fb_probe(struct platform_device *pdev)
fbinfo->flags = FBINFO_FLAG_DEFAULT;
fbinfo->pseudo_palette = &fbi->pseudo_pal;
- ret = request_irq(irq, nuc900fb_irqhandler, 0,
- pdev->name, fbinfo);
+ ret = request_irq(irq, nuc900fb_irqhandler, 0, pdev->name, fbi);
if (ret) {
dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
irq, ret);
^ permalink raw reply related
* Re: [PATCH 2/3] video: hx8357: Make IM pins optional
From: Jingoo Han @ 2013-07-16 0:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1373902022-20439-3-git-send-email-maxime.ripard@free-electrons.com>
On Tuesday, July 16, 2013 12:27 AM, Maxime Ripard wrote:
>
> The IM pins of the HX8357 controller are used to define the interface
> used to feed pixel stream to the LCD panel.
>
> Most of the time, these pins are directly routed to either the ground or
> the VCC to set their values.
>
> Remove the need to assign GPIOs to these pins when we are in such a case.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> drivers/video/backlight/hx8357.c | 52 +++++++++++++++++++++++-----------------
> 1 file changed, 30 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
> index a0482b5..ed94796 100644
> --- a/drivers/video/backlight/hx8357.c
> +++ b/drivers/video/backlight/hx8357.c
> @@ -76,6 +76,7 @@ struct hx8357_data {
> unsigned reset;
> struct spi_device *spi;
> int state;
> + bool use_im_pins;
> };
>
> static u8 hx8357_seq_power[] = {
> @@ -250,9 +251,11 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
> * Set the interface selection pins to SPI mode, with three
> * wires
> */
> - gpio_set_value_cansleep(lcd->im_pins[0], 1);
> - gpio_set_value_cansleep(lcd->im_pins[1], 0);
> - gpio_set_value_cansleep(lcd->im_pins[2], 1);
> + if (lcd->use_im_pins) {
> + gpio_set_value_cansleep(lcd->im_pins[0], 1);
> + gpio_set_value_cansleep(lcd->im_pins[1], 0);
> + gpio_set_value_cansleep(lcd->im_pins[2], 1);
> + }
>
> /* Reset the screen */
> gpio_set_value(lcd->reset, 1);
> @@ -424,26 +427,31 @@ static int hx8357_probe(struct spi_device *spi)
> return -EINVAL;
> }
>
> - for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
> - lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
> - "im-gpios", i);
> - if (lcd->im_pins[i] = -EPROBE_DEFER) {
> - dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
> - return -EPROBE_DEFER;
> - }
> - if (!gpio_is_valid(lcd->im_pins[i])) {
> - dev_err(&spi->dev, "Missing dt property: im-gpios\n");
> - return -EINVAL;
> + if (of_find_property(spi->dev.of_node, "im-gpios", NULL)) {
> + lcd->use_im_pins = 1;
> +
> + for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
> + lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
> + "im-gpios", i);
> + if (lcd->im_pins[i] = -EPROBE_DEFER) {
> + dev_info(&spi->dev, "GPIO requested is not here yet, deferring the
> probe\n");
> + return -EPROBE_DEFER;
> + }
> + if (!gpio_is_valid(lcd->im_pins[i])) {
> + dev_err(&spi->dev, "Missing dt property: im-gpios\n");
> + return -EINVAL;
> + }
> +
> + ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
> + GPIOF_OUT_INIT_LOW, "im_pins");
This makes a checkpatch warning such as 'WARNING: line over 80 characters'.
How about the following?
ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
GPIOF_OUT_INIT_LOW, "im_pins");
> + if (ret) {
> + dev_err(&spi->dev, "failed to request gpio %d: %d\n",
> + lcd->im_pins[i], ret);
> + return -EINVAL;
> + }
> }
> -
> - ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
> - GPIOF_OUT_INIT_LOW, "im_pins");
> - if (ret) {
> - dev_err(&spi->dev, "failed to request gpio %d: %d\n",
> - lcd->im_pins[i], ret);
> - return -EINVAL;
> - }
> - }
> + } else
> + lcd->use_im_pins = 0;
According to the 'Documentation/CodingStyle', braces are necessary as below.
} else {
lcd->use_im_pins = 0;
}
Others look good.
Acked-by: Jingoo Han <jg1.han@samsung.com>
Best regards,
Jingoo Han
>
> lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops);
> if (IS_ERR(lcdev)) {
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] logo: Remove trailing whitespace from logo_linux_clut224.ppm
From: Linus Torvalds @ 2013-07-16 1:02 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Jean-Christophe Plagniol-Villard, Tomi Valkeinen,
linux-fbdev@vger.kernel.org, Linux Kernel Mailing List
In-Reply-To: <1373876954-30437-1-git-send-email-geert@linux-m68k.org>
On Mon, Jul 15, 2013 at 1:29 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> Commit ad81f0545ef01ea651886dddac4bef6cec930092 ("Linux 3.11-rc1")
> replaced the Standard 224-color Linux logo, and introduced lots of
> trailing whitespace. Remove it again.
The logo is temporary, and I'd rather keep it the way it is so that a
simple revert will fix things up again..
That said, even if it wasn't temporary, I think we might be better off
with the raw format that the netpbm tools generate these days. It was
actually slightly annoying to get that big diff from a small edit, and
it was the result of either the original logo ASCII representation
having been cleaned up excessively before, or possibly just the netpbm
tools having changed their output radically.
Of course, it would be even better if we actually used some saner
format. I'm not exactly artistic, so making that whole silly logo
change took more time than it really should have. But what was
*really* painful was to fight the horrible ppm format conversion
issues, and how we only accept that legacy ascii version etc.
I guess it doesn't matter, since it's not like that thing normally
changes, so it's likely not really worth fixing. But it did make me go
"does it really have to be this arcane?"
Linus
^ permalink raw reply
* Re: [PATCH] video: nuc900fb: fix to pass correct device identity to request_irq()
From: Wan ZongShun @ 2013-07-16 1:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPgLHd9CZ=VponJTbTGKTXVTdvMQM6_T+-RWuPMrk0WYZPbW1Q@mail.gmail.com>
2013/7/16 Wei Yongjun <weiyj.lk@gmail.com>:
> The IRQ handler nuc900fb_irqhandler() use dev_id as a type of
> struct nuc900fb_info *, so we should pass fbi as the device
> identity to request_irq().
>
> Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Acked-by: Wan Zongshun <mcuos.com@gmail.com>
Thanks!
Vincent Wan.
> ---
> Was 'video: nuc900fb: fix to pass correct device identity to free_irq()'
> ---
> drivers/video/nuc900fb.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
> index 8c527e5..796e511 100644
> --- a/drivers/video/nuc900fb.c
> +++ b/drivers/video/nuc900fb.c
> @@ -587,8 +587,7 @@ static int nuc900fb_probe(struct platform_device *pdev)
> fbinfo->flags = FBINFO_FLAG_DEFAULT;
> fbinfo->pseudo_palette = &fbi->pseudo_pal;
>
> - ret = request_irq(irq, nuc900fb_irqhandler, 0,
> - pdev->name, fbinfo);
> + ret = request_irq(irq, nuc900fb_irqhandler, 0, pdev->name, fbi);
> if (ret) {
> dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
> irq, ret);
>
>
--
Wan ZongShun.
www.mcuos.com
^ permalink raw reply
* Re: [PATCH 3/3] fb: backlight: HX8357: Add HX8369 support
From: Jingoo Han @ 2013-07-16 2:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1373902022-20439-4-git-send-email-maxime.ripard@free-electrons.com>
On Tuesday, July 16, 2013 12:27 AM, Maxime Ripard wrote:
>
> From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
>
> Add support for the Himax HX8369 controller as it is quite similar to the
> hx8357.
>
> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Hi Maxime Ripard,
I reviewed this patch with Himax HX8369 datasheet.
I cannot find any problems. It looks good.
However, if possible, please add comment on huge delays such as
msleep(120), msleep(100), etc.
Acked-by: Jingoo Han <jg1.han@samsung.com>
Best regards,
Jingoo Han
> ---
> drivers/video/backlight/hx8357.c | 203 ++++++++++++++++++++++++++++++++++++---
> 1 file changed, 188 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
> index ed94796..b035fab 100644
> --- a/drivers/video/backlight/hx8357.c
> +++ b/drivers/video/backlight/hx8357.c
> @@ -71,6 +71,18 @@
> #define HX8357_SET_POWER_NORMAL 0xd2
> #define HX8357_SET_PANEL_RELATED 0xe9
>
> +#define HX8369_SET_DISPLAY_BRIGHTNESS 0x51
> +#define HX8369_WRITE_CABC_DISPLAY_VALUE 0x53
> +#define HX8369_WRITE_CABC_BRIGHT_CTRL 0x55
> +#define HX8369_WRITE_CABC_MIN_BRIGHTNESS 0x5e
> +#define HX8369_SET_POWER 0xb1
> +#define HX8369_SET_DISPLAY_MODE 0xb2
> +#define HX8369_SET_DISPLAY_WAVEFORM_CYC 0xb4
> +#define HX8369_SET_VCOM 0xb6
> +#define HX8369_SET_EXTENSION_COMMAND 0xb9
> +#define HX8369_SET_GIP 0xd5
> +#define HX8369_SET_GAMMA_CURVE_RELATED 0xe0
> +
> struct hx8357_data {
> unsigned im_pins[HX8357_NUM_IM_PINS];
> unsigned reset;
> @@ -144,6 +156,61 @@ static u8 hx8357_seq_display_mode[] = {
> HX8357_SET_DISPLAY_MODE_RGB_INTERFACE,
> };
>
> +static u8 hx8369_seq_write_CABC_min_brightness[] = {
> + HX8369_WRITE_CABC_MIN_BRIGHTNESS, 0x00,
> +};
> +
> +static u8 hx8369_seq_write_CABC_control[] = {
> + HX8369_WRITE_CABC_DISPLAY_VALUE, 0x24,
> +};
> +
> +static u8 hx8369_seq_set_display_brightness[] = {
> + HX8369_SET_DISPLAY_BRIGHTNESS, 0xFF,
> +};
> +
> +static u8 hx8369_seq_write_CABC_control_setting[] = {
> + HX8369_WRITE_CABC_BRIGHT_CTRL, 0x02,
> +};
> +
> +static u8 hx8369_seq_extension_command[] = {
> + HX8369_SET_EXTENSION_COMMAND, 0xff, 0x83, 0x69,
> +};
> +
> +static u8 hx8369_seq_display_related[] = {
> + HX8369_SET_DISPLAY_MODE, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00,
> + 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x01,
> +};
> +
> +static u8 hx8369_seq_panel_waveform_cycle[] = {
> + HX8369_SET_DISPLAY_WAVEFORM_CYC, 0x0a, 0x1d, 0x80, 0x06, 0x02,
> +};
> +
> +static u8 hx8369_seq_set_address_mode[] = {
> + HX8357_SET_ADDRESS_MODE, 0x00,
> +};
> +
> +static u8 hx8369_seq_vcom[] = {
> + HX8369_SET_VCOM, 0x3e, 0x3e,
> +};
> +
> +static u8 hx8369_seq_gip[] = {
> + HX8369_SET_GIP, 0x00, 0x01, 0x03, 0x25, 0x01, 0x02, 0x28, 0x70,
> + 0x11, 0x13, 0x00, 0x00, 0x40, 0x26, 0x51, 0x37, 0x00, 0x00, 0x71,
> + 0x35, 0x60, 0x24, 0x07, 0x0f, 0x04, 0x04,
> +};
> +
> +static u8 hx8369_seq_power[] = {
> + HX8369_SET_POWER, 0x01, 0x00, 0x34, 0x03, 0x00, 0x11, 0x11, 0x32,
> + 0x2f, 0x3f, 0x3f, 0x01, 0x3a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
> +};
> +
> +static u8 hx8369_seq_gamma_curve_related[] = {
> + HX8369_SET_GAMMA_CURVE_RELATED, 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d,
> + 0x2e, 0x4a, 0x08, 0x0e, 0x0f, 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
> + 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, 0x2e, 0x4a, 0x08, 0x0e, 0x0f,
> + 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
> +};
> +
> static int hx8357_spi_write_then_read(struct lcd_device *lcdev,
> u8 *txbuf, u16 txlen,
> u8 *rxbuf, u16 rxlen)
> @@ -242,6 +309,18 @@ static int hx8357_exit_standby(struct lcd_device *lcdev)
> return 0;
> }
>
> +static void hx8357_lcd_reset(struct lcd_device *lcdev)
> +{
> + struct hx8357_data *lcd = lcd_get_data(lcdev);
> +
> + gpio_set_value(lcd->reset, 1);
> + usleep_range(10000, 12000);
> + gpio_set_value(lcd->reset, 0);
> + usleep_range(10000, 12000);
> + gpio_set_value(lcd->reset, 1);
> + msleep(120);
> +}
> +
> static int hx8357_lcd_init(struct lcd_device *lcdev)
> {
> struct hx8357_data *lcd = lcd_get_data(lcdev);
> @@ -257,14 +336,6 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
> gpio_set_value_cansleep(lcd->im_pins[2], 1);
> }
>
> - /* Reset the screen */
> - gpio_set_value(lcd->reset, 1);
> - usleep_range(10000, 12000);
> - gpio_set_value(lcd->reset, 0);
> - usleep_range(10000, 12000);
> - gpio_set_value(lcd->reset, 1);
> - msleep(120);
> -
> ret = hx8357_spi_write_array(lcdev, hx8357_seq_power,
> ARRAY_SIZE(hx8357_seq_power));
> if (ret < 0)
> @@ -359,6 +430,94 @@ static int hx8357_lcd_init(struct lcd_device *lcdev)
> return 0;
> }
>
> +static int hx8369_lcd_init(struct lcd_device *lcdev)
> +{
> + int ret;
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_extension_command,
> + ARRAY_SIZE(hx8369_seq_extension_command));
> + if (ret < 0)
> + return ret;
> + usleep_range(10000, 12000);
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_display_related,
> + ARRAY_SIZE(hx8369_seq_display_related));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_panel_waveform_cycle,
> + ARRAY_SIZE(hx8369_seq_panel_waveform_cycle));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_address_mode,
> + ARRAY_SIZE(hx8369_seq_set_address_mode));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_vcom,
> + ARRAY_SIZE(hx8369_seq_vcom));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_gip,
> + ARRAY_SIZE(hx8369_seq_gip));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_power,
> + ARRAY_SIZE(hx8369_seq_power));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
> + if (ret < 0)
> + return ret;
> +
> + msleep(120);
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_gamma_curve_related,
> + ARRAY_SIZE(hx8369_seq_gamma_curve_related));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
> + if (ret < 0)
> + return ret;
> + usleep_range(1000, 1200);
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_write_CABC_control,
> + ARRAY_SIZE(hx8369_seq_write_CABC_control));
> + if (ret < 0)
> + return ret;
> + usleep_range(10000, 12000);
> +
> + ret = hx8357_spi_write_array(lcdev,
> + hx8369_seq_write_CABC_control_setting,
> + ARRAY_SIZE(hx8369_seq_write_CABC_control_setting));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_array(lcdev,
> + hx8369_seq_write_CABC_min_brightness,
> + ARRAY_SIZE(hx8369_seq_write_CABC_min_brightness));
> + if (ret < 0)
> + return ret;
> + usleep_range(10000, 12000);
> +
> + ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_display_brightness,
> + ARRAY_SIZE(hx8369_seq_set_display_brightness));
> + if (ret < 0)
> + return ret;
> +
> + ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
> + if (ret < 0)
> + return ret;
> + msleep(100);
> +
> + return 0;
> +}
> +
> #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
>
> static int hx8357_set_power(struct lcd_device *lcdev, int power)
> @@ -391,10 +550,24 @@ static struct lcd_ops hx8357_ops = {
> .get_power = hx8357_get_power,
> };
>
> +static const struct of_device_id hx8357_dt_ids[] = {
> + {
> + .compatible = "himax,hx8357",
> + .data = hx8357_lcd_init,
> + },
> + {
> + .compatible = "himax,hx8369",
> + .data = hx8369_lcd_init,
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
> +
> static int hx8357_probe(struct spi_device *spi)
> {
> struct lcd_device *lcdev;
> struct hx8357_data *lcd;
> + const struct of_device_id *match;
> int i, ret;
>
> lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
> @@ -411,6 +584,10 @@ static int hx8357_probe(struct spi_device *spi)
>
> lcd->spi = spi;
>
> + match = of_match_device(hx8357_dt_ids, &spi->dev);
> + if (!match || !match->data)
> + return -EINVAL;
> +
> lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0);
> if (!gpio_is_valid(lcd->reset)) {
> dev_err(&spi->dev, "Missing dt property: gpios-reset\n");
> @@ -460,7 +637,9 @@ static int hx8357_probe(struct spi_device *spi)
> }
> spi_set_drvdata(spi, lcdev);
>
> - ret = hx8357_lcd_init(lcdev);
> + hx8357_lcd_reset(lcdev);
> +
> + ret = ((int (*)(struct lcd_device *))match->data)(lcdev);
> if (ret) {
> dev_err(&spi->dev, "Couldn't initialize panel\n");
> goto init_error;
> @@ -483,12 +662,6 @@ static int hx8357_remove(struct spi_device *spi)
> return 0;
> }
>
> -static const struct of_device_id hx8357_dt_ids[] = {
> - { .compatible = "himax,hx8357" },
> - {},
> -};
> -MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
> -
> static struct spi_driver hx8357_driver = {
> .probe = hx8357_probe,
> .remove = hx8357_remove,
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] logo: Remove trailing whitespace from logo_linux_clut224.ppm
From: H. Peter Anvin @ 2013-07-16 2:39 UTC (permalink / raw)
To: Linus Torvalds
Cc: Geert Uytterhoeven, Jean-Christophe Plagniol-Villard,
Tomi Valkeinen, linux-fbdev@vger.kernel.org,
Linux Kernel Mailing List
In-Reply-To: <CA+55aFxGymOvvaYfOg22AdHpxEOuOctfC8vRW+_u=vtua8Dksg@mail.gmail.com>
On 07/15/2013 06:02 PM, Linus Torvalds wrote:
>
> That said, even if it wasn't temporary, I think we might be better off
> with the raw format that the netpbm tools generate these days.
>
For "these days" meaning "since the 1980s". I would suggest bumping up
to the 1990s and go with PNG.
-hpa
^ permalink raw reply
* Re: [PATCH 2/3] video: hx8357: Make IM pins optional
From: Mike Galbraith @ 2013-07-16 3:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <003501ce81be$4a945ed0$dfbd1c70$@samsung.com>
On Tue, 2013-07-16 at 09:49 +0900, Jingoo Han wrote:
> On Tuesday, July 16, 2013 12:27 AM, Maxime Ripard wrote:
> > +
> > + ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
> > + GPIOF_OUT_INIT_LOW, "im_pins");
>
> This makes a checkpatch warning such as 'WARNING: line over 80 characters'.
> How about the following?
>
> ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
> GPIOF_OUT_INIT_LOW, "im_pins");
IIRC, some maintainers gripe (davem?) when they see such alignment,
preferring the original arg below arg alignment vs strict 80 column.
-Mike
^ permalink raw reply
* Re: [PATCH] logo: Remove trailing whitespace from logo_linux_clut224.ppm
From: Geert Uytterhoeven @ 2013-07-16 7:43 UTC (permalink / raw)
To: Linus Torvalds
Cc: Jean-Christophe Plagniol-Villard, Tomi Valkeinen,
linux-fbdev@vger.kernel.org, Linux Kernel Mailing List,
Rob Landley
In-Reply-To: <CA+55aFxGymOvvaYfOg22AdHpxEOuOctfC8vRW+_u=vtua8Dksg@mail.gmail.com>
Hi Linus,
On Tue, Jul 16, 2013 at 3:02 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Mon, Jul 15, 2013 at 1:29 AM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
>> Commit ad81f0545ef01ea651886dddac4bef6cec930092 ("Linux 3.11-rc1")
>> replaced the Standard 224-color Linux logo, and introduced lots of
>> trailing whitespace. Remove it again.
>
> The logo is temporary, and I'd rather keep it the way it is so that a
> simple revert will fix things up again..
OK, that's a good reason. But unlike last time with Tuz, you can't revert
the whole commit, as that also reverts the version ;-)
> That said, even if it wasn't temporary, I think we might be better off
> with the raw format that the netpbm tools generate these days. It was
> actually slightly annoying to get that big diff from a small edit, and
> it was the result of either the original logo ASCII representation
> having been cleaned up excessively before, or possibly just the netpbm
> tools having changed their output radically.
It seems there are different versions. My (Ubuntu 12.04 LTS) version of
pnmnoraw doesn't add trailing whitespace, but groups the values per
pixel. The old version used to generate the pre-v3.11-rc1 logo didn't
group the values, but used he same width for all fields.
> Of course, it would be even better if we actually used some saner
> format. I'm not exactly artistic, so making that whole silly logo
> change took more time than it really should have. But what was
> *really* painful was to fight the horrible ppm format conversion
> issues, and how we only accept that legacy ascii version etc.
When the logo conversion code was written (before we just had C header
files with arrays, which were a hell to update), my requirements were:
1. The format must be easy to generate with commonly used tools,
2. The format must be ASCII, to allow emailing of patches,
3. The format must be easily parsable, without relying on external tools and
libraries.
Thanks to "GIT binary patch", 2 is no longer required.
If we switch to e.g. PNG, we may have to rely on one more external library,
upsetting Rob.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH v3 3/7] at91/avr32/atmel_lcdfb: prepare clk before calling enable
From: Boris BREZILLON @ 2013-07-16 15:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1373986995-23899-1-git-send-email-b.brezillon@overkiz.com>
Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to
avoid common clk framework warnings.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
drivers/video/atmel_lcdfb.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index ece49d5..bf9c5d0 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -954,14 +954,14 @@ static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
{
- clk_enable(sinfo->bus_clk);
- clk_enable(sinfo->lcdc_clk);
+ clk_prepare_enable(sinfo->bus_clk);
+ clk_prepare_enable(sinfo->lcdc_clk);
}
static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
{
- clk_disable(sinfo->bus_clk);
- clk_disable(sinfo->lcdc_clk);
+ clk_disable_unprepare(sinfo->bus_clk);
+ clk_disable_unprepare(sinfo->lcdc_clk);
}
#ifdef CONFIG_OF
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH 3/3] fb: backlight: HX8357: Add HX8369 support
From: 'Maxime Ripard' @ 2013-07-16 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <003601ce81c8$c2573320$47059960$@samsung.com>
[-- Attachment #1: Type: text/plain, Size: 1039 bytes --]
Hi Jingoo,
On Tue, Jul 16, 2013 at 11:04:09AM +0900, Jingoo Han wrote:
> On Tuesday, July 16, 2013 12:27 AM, Maxime Ripard wrote:
> >
> > From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> >
> > Add support for the Himax HX8369 controller as it is quite similar to the
> > hx8357.
> >
> > Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> Hi Maxime Ripard,
>
> I reviewed this patch with Himax HX8369 datasheet.
> I cannot find any problems. It looks good.
>
> However, if possible, please add comment on huge delays such as
> msleep(120), msleep(100), etc.
Right. I'll send a follow-up patch if this is merged right away, or
merge the comments in the next iteration of the patches.
> Acked-by: Jingoo Han <jg1.han@samsung.com>
Thanks for taking the time to review this!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH 0/3] Few ignored framebuffer fixes/additions
From: Andrew Morton @ 2013-07-17 21:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1373902022-20439-1-git-send-email-maxime.ripard@free-electrons.com>
On Mon, 15 Jul 2013 17:26:59 +0200 Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> Sorry to bother you again with the framebuffer stuff but the new
> maintainer doesn't appear to be responsive either.
Jean-Christophe is doing things - on 11 July he sent out a call for
late patches to linux-fbdev@vger.kernel.org.
So hopefully the resend of this patch series will be handled
appropriately?
^ permalink raw reply
* Re: [PATCH RESEND] video: mxsfb: Let device core handle pinctrl
From: Andrew Morton @ 2013-07-17 22:24 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1373923884-13332-1-git-send-email-festevam@gmail.com>
On Mon, 15 Jul 2013 18:31:24 -0300 Fabio Estevam <festevam@gmail.com> wrote:
> From: Fabio Estevam <fabio.estevam@freescale.com>
>
> Since commit ab78029 (drivers/pinctrl: grab default handles from device core)
> we can rely on device core for handling pinctrl, so remove
> devm_pinctrl_get_select_default() from the driver.
>
> Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
> Acked-by: Shawn Guo <shawn.guo@linaro.org>
> ---
> Andrew,
>
> Should this go via your tree?
Well, no, it should really be reviewed by and merged by
Jean-Christophe. Is there a problem in fbdev land?
^ permalink raw reply
* [PATCH 00/15] PHY framework
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
Added a generic PHY framework that provides a set of APIs for the PHY drivers
to create/destroy a PHY and APIs for the PHY users to obtain a reference to
the PHY with or without using phandle.
This framework will be of use only to devices that uses external PHY (PHY
functionality is not embedded within the controller).
The intention of creating this framework is to bring the phy drivers spread
all over the Linux kernel to drivers/phy to increase code re-use and to
increase code maintainability.
Comments to make PHY as bus wasn't done because PHY devices can be part of
other bus and making a same device attached to multiple bus leads to bad
design.
If the PHY driver has to send notification on connect/disconnect, the PHY
driver should make use of the extcon framework. Using this susbsystem
to use extcon framwork will have to be analysed.
Exynos MIPI CSIS/DSIM PHY and Displayport PHY have started using this
framework. Have included those patches also in this series.
twl4030-usb and omap-usb2 have also been adapted to this framework.
These patches are also available @
git://gitorious.org/linuxphy/linuxphy.git tags/phy-for-v3.12
Jingoo Han (3):
phy: Add driver for Exynos DP PHY
video: exynos_dp: remove non-DT support for Exynos Display Port
video: exynos_dp: Use the generic PHY driver
Kishon Vijay Abraham I (8):
drivers: phy: add generic PHY framework
usb: phy: omap-usb2: use the new generic PHY framework
usb: phy: twl4030: use the new generic PHY framework
ARM: OMAP: USB: Add phy binding information
ARM: dts: omap: update usb_otg_hs data
usb: musb: omap2430: use the new generic PHY framework
usb: phy: omap-usb2: remove *set_suspend* callback from omap-usb2
usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops
Sylwester Nawrocki (4):
phy: Add driver for Exynos MIPI CSIS/DSIM DPHYs
video: exynos_mipi_dsim: Use the generic PHY driver
exynos4-is: Use the generic MIPI CSIS PHY driver
ARM: Samsung: Remove the MIPI PHY setup code
.../devicetree/bindings/phy/phy-bindings.txt | 66 +++
.../devicetree/bindings/phy/samsung-phy.txt | 22 +
Documentation/devicetree/bindings/usb/omap-usb.txt | 5 +
Documentation/devicetree/bindings/usb/usb-phy.txt | 6 +
.../devicetree/bindings/video/exynos_dp.txt | 18 +-
Documentation/phy.txt | 129 +++++
MAINTAINERS | 7 +
arch/arm/boot/dts/omap3-beagle-xm.dts | 2 +
arch/arm/boot/dts/omap3-evm.dts | 2 +
arch/arm/boot/dts/omap3-overo.dtsi | 2 +
arch/arm/boot/dts/omap4.dtsi | 3 +
arch/arm/boot/dts/twl4030.dtsi | 1 +
arch/arm/mach-exynos/include/mach/regs-pmu.h | 5 -
arch/arm/mach-omap2/usb-musb.c | 3 +
arch/arm/mach-s5pv210/include/mach/regs-clock.h | 4 -
arch/arm/plat-samsung/Kconfig | 5 -
arch/arm/plat-samsung/Makefile | 1 -
arch/arm/plat-samsung/setup-mipiphy.c | 60 ---
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/media/platform/exynos4-is/mipi-csis.c | 16 +-
drivers/phy/Kconfig | 28 +
drivers/phy/Makefile | 7 +
drivers/phy/phy-core.c | 544 ++++++++++++++++++++
drivers/phy/phy-exynos-dp-video.c | 111 ++++
drivers/phy/phy-exynos-mipi-video.c | 169 ++++++
drivers/usb/musb/Kconfig | 1 +
drivers/usb/musb/musb_core.c | 1 +
drivers/usb/musb/musb_core.h | 3 +
drivers/usb/musb/omap2430.c | 26 +-
drivers/usb/phy/Kconfig | 1 +
drivers/usb/phy/phy-omap-usb2.c | 60 ++-
drivers/usb/phy/phy-twl4030-usb.c | 63 ++-
drivers/video/exynos/Kconfig | 2 +-
drivers/video/exynos/exynos_dp_core.c | 132 ++---
drivers/video/exynos/exynos_dp_core.h | 110 ++++
drivers/video/exynos/exynos_dp_reg.c | 2 -
drivers/video/exynos/exynos_mipi_dsi.c | 19 +-
include/linux/phy/phy.h | 344 +++++++++++++
include/linux/platform_data/mipi-csis.h | 11 +-
include/linux/usb/musb.h | 3 +
include/video/exynos_dp.h | 131 -----
include/video/exynos_mipi_dsim.h | 6 +-
43 files changed, 1746 insertions(+), 389 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/phy-bindings.txt
create mode 100644 Documentation/devicetree/bindings/phy/samsung-phy.txt
create mode 100644 Documentation/phy.txt
delete mode 100644 arch/arm/plat-samsung/setup-mipiphy.c
create mode 100644 drivers/phy/Kconfig
create mode 100644 drivers/phy/Makefile
create mode 100644 drivers/phy/phy-core.c
create mode 100644 drivers/phy/phy-exynos-dp-video.c
create mode 100644 drivers/phy/phy-exynos-mipi-video.c
create mode 100644 include/linux/phy/phy.h
delete mode 100644 include/video/exynos_dp.h
--
1.7.10.4
^ permalink raw reply
* [PATCH 01/15] drivers: phy: add generic PHY framework
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1374129984-765-1-git-send-email-kishon@ti.com>
The PHY framework provides a set of APIs for the PHY drivers to
create/destroy a PHY and APIs for the PHY users to obtain a reference to the
PHY with or without using phandle. For dt-boot, the PHY drivers should
also register *PHY provider* with the framework.
PHY drivers should create the PHY by passing id and ops like init, exit,
power_on and power_off. This framework is also pm runtime enabled.
The documentation for the generic PHY framework is added in
Documentation/phy.txt and the documentation for dt binding can be found at
Documentation/devicetree/bindings/phy/phy-bindings.txt
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
.../devicetree/bindings/phy/phy-bindings.txt | 66 +++
Documentation/phy.txt | 129 +++++
MAINTAINERS | 7 +
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/phy/Kconfig | 13 +
drivers/phy/Makefile | 5 +
drivers/phy/phy-core.c | 544 ++++++++++++++++++++
include/linux/phy/phy.h | 344 +++++++++++++
9 files changed, 1112 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-bindings.txt
create mode 100644 Documentation/phy.txt
create mode 100644 drivers/phy/Kconfig
create mode 100644 drivers/phy/Makefile
create mode 100644 drivers/phy/phy-core.c
create mode 100644 include/linux/phy/phy.h
diff --git a/Documentation/devicetree/bindings/phy/phy-bindings.txt b/Documentation/devicetree/bindings/phy/phy-bindings.txt
new file mode 100644
index 0000000..8ae844f
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-bindings.txt
@@ -0,0 +1,66 @@
+This document explains only the device tree data binding. For general
+information about PHY subsystem refer to Documentation/phy.txt
+
+PHY device node
+=======+
+Required Properties:
+#phy-cells: Number of cells in a PHY specifier; The meaning of all those
+ cells is defined by the binding for the phy node. The PHY
+ provider can use the values in cells to find the appropriate
+ PHY.
+
+For example:
+
+phys: phy {
+ compatible = "xxx";
+ reg = <...>;
+ .
+ .
+ #phy-cells = <1>;
+ .
+ .
+};
+
+That node describes an IP block (PHY provider) that implements 2 different PHYs.
+In order to differentiate between these 2 PHYs, an additonal specifier should be
+given while trying to get a reference to it.
+
+PHY user node
+======+
+Required Properties:
+phys : the phandle for the PHY device (used by the PHY subsystem)
+phy-names : the names of the PHY corresponding to the PHYs present in the
+ *phys* phandle
+
+Example 1:
+usb1: usb_otg_ss@xxx {
+ compatible = "xxx";
+ reg = <xxx>;
+ .
+ .
+ phys = <&usb2_phy>, <&usb3_phy>;
+ phy-names = "usb2phy", "usb3phy";
+ .
+ .
+};
+
+This node represents a controller that uses two PHYs, one for usb2 and one for
+usb3.
+
+Example 2:
+usb2: usb_otg_ss@xxx {
+ compatible = "xxx";
+ reg = <xxx>;
+ .
+ .
+ phys = <&phys 1>;
+ phy-names = "usbphy";
+ .
+ .
+};
+
+This node represents a controller that uses one of the PHYs of the PHY provider
+device defined previously. Note that the phy handle has an additional specifier
+"1" to differentiate between the two PHYs.
diff --git a/Documentation/phy.txt b/Documentation/phy.txt
new file mode 100644
index 0000000..05f8fda
--- /dev/null
+++ b/Documentation/phy.txt
@@ -0,0 +1,129 @@
+ PHY SUBSYSTEM
+ Kishon Vijay Abraham I <kishon@ti.com>
+
+This document explains the Generic PHY Framework along with the APIs provided,
+and how-to-use.
+
+1. Introduction
+
+*PHY* is the abbreviation for physical layer. It is used to connect a device
+to the physical medium e.g., the USB controller has a PHY to provide functions
+such as serialization, de-serialization, encoding, decoding and is responsible
+for obtaining the required data transmission rate. Note that some USB
+controllers have PHY functionality embedded into it and others use an external
+PHY. Other peripherals that use PHY include Wireless LAN, Ethernet,
+SATA etc.
+
+The intention of creating this framework is to bring the PHY drivers spread
+all over the Linux kernel to drivers/phy to increase code re-use and for
+better code maintainability.
+
+This framework will be of use only to devices that use external PHY (PHY
+functionality is not embedded within the controller).
+
+2. Registering/Unregistering the PHY provider
+
+PHY provider refers to an entity that implements one or more PHY instances.
+For the simple case where the PHY provider implements only a single instance of
+the PHY, the framework provides its own implementation of of_xlate in
+of_phy_simple_xlate. If the PHY provider implements multiple instances, it
+should provide its own implementation of of_xlate. of_xlate is used only for
+dt boot case.
+
+struct phy_provider *__of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args));
+struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+
+__of_phy_provider_register and __devm_of_phy_provider_register can be used to
+register the phy_provider and it takes device, owner and of_xlate as
+arguments. For the dt boot case, all PHY providers should use one of the above
+2 APIs to register the PHY provider.
+
+void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider);
+void of_phy_provider_unregister(struct phy_provider *phy_provider);
+
+devm_of_phy_provider_unregister and of_phy_provider_unregister can be used to
+unregister the PHY.
+
+3. Creating the PHY
+
+The PHY driver should create the PHY in order for other peripheral controllers
+to make use of it. The PHY framework provides 2 APIs to create the PHY.
+
+struct phy *phy_create(struct device *dev, u8 id, const struct phy_ops *ops,
+ const char *label);
+extern struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label);
+
+The PHY drivers can use one of the above 2 APIs to create the PHY by passing
+the device pointer, id, phy ops, label and a driver data.
+phy_ops is a set of function pointers for performing PHY operations such as
+init, exit, power_on and power_off. *label* is mandatory for non-dt boot case
+and it should be unique as well.
+
+Inorder to dereference the private data (in phy_ops), the phy provider driver
+can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
+phy_ops to get back the private data.
+
+4. Getting a reference to the PHY
+
+Before the controller can make use of the PHY, it has to get a reference to
+it. This framework provides the following APIs to get a reference to the PHY.
+
+struct phy *phy_get(struct device *dev, const char *string);
+struct phy *devm_phy_get(struct device *dev, const char *string);
+
+phy_get and devm_phy_get can be used to get the PHY. In the case of dt boot,
+the string arguments should contain the phy name as given in the dt data and
+in the case of non-dt boot, it should contain the label of the PHY.
+The only difference between the two APIs is that devm_phy_get associates the
+device with the PHY using devres on successful PHY get. On driver detach,
+release function is invoked on the the devres data and devres data is freed.
+
+5. Releasing a reference to the PHY
+
+When the controller no longer needs the PHY, it has to release the reference
+to the PHY it has obtained using the APIs mentioned in the above section. The
+PHY framework provides 2 APIs to release a reference to the PHY.
+
+void phy_put(struct phy *phy);
+void devm_phy_put(struct device *dev, struct phy *phy);
+
+Both these APIs are used to release a reference to the PHY and devm_phy_put
+destroys the devres associated with this PHY.
+
+6. Destroying the PHY
+
+When the driver that created the PHY is unloaded, it should destroy the PHY it
+created using one of the following 2 APIs.
+
+void phy_destroy(struct phy *phy);
+void devm_phy_destroy(struct device *dev, struct phy *phy);
+
+Both these APIs destroy the PHY and devm_phy_destroy destroys the devres
+associated with this PHY.
+
+7. PM Runtime
+
+This subsystem is pm runtime enabled. So while creating the PHY,
+pm_runtime_enable of the phy device created by this subsystem is called and
+while destroying the PHY, pm_runtime_disable is called. Note that the phy
+device created by this subsystem will be a child of the device that calls
+phy_create (PHY provider device).
+
+So pm_runtime_get_sync of the phy_device created by this subsystem will invoke
+pm_runtime_get_sync of PHY provider device because of parent-child relationship.
+It should also be noted that phy_power_on and phy_power_off performs
+phy_pm_runtime_get_sync and phy_pm_runtime_put respectively.
+There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync,
+phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and
+phy_pm_runtime_forbid for performing PM operations.
+
+8. DeviceTree Binding
+
+The documentation for PHY dt binding can be found @
+Documentation/devicetree/bindings/phy/phy-bindings.txt
diff --git a/MAINTAINERS b/MAINTAINERS
index bf61e04..dd03889 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3594,6 +3594,13 @@ S: Maintained
F: include/asm-generic
F: include/uapi/asm-generic
+GENERIC PHY FRAMEWORK
+M: Kishon Vijay Abraham I <kishon@ti.com>
+L: linux-kernel@vger.kernel.org
+S: Supported
+F: drivers/phy/
+F: include/linux/phy/
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm@vger.kernel.org
diff --git a/drivers/Kconfig b/drivers/Kconfig
index aa43b91..8f45144 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -166,4 +166,6 @@ source "drivers/reset/Kconfig"
source "drivers/fmc/Kconfig"
+source "drivers/phy/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ab93de8..687da89 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -8,6 +8,8 @@
obj-y += irqchip/
obj-y += bus/
+obj-$(CONFIG_GENERIC_PHY) += phy/
+
# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-y += pinctrl/
obj-y += gpio/
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
new file mode 100644
index 0000000..5f85909
--- /dev/null
+++ b/drivers/phy/Kconfig
@@ -0,0 +1,13 @@
+#
+# PHY
+#
+
+menuconfig GENERIC_PHY
+ tristate "PHY Subsystem"
+ help
+ Generic PHY support.
+
+ This framework is designed to provide a generic interface for PHY
+ devices present in the kernel. This layer will have the generic
+ API by which phy drivers can create PHY using the phy framework and
+ phy users can obtain reference to the PHY.
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
new file mode 100644
index 0000000..9e9560f
--- /dev/null
+++ b/drivers/phy/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the phy drivers.
+#
+
+obj-$(CONFIG_GENERIC_PHY) += phy-core.o
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
new file mode 100644
index 0000000..6c75dc3
--- /dev/null
+++ b/drivers/phy/phy-core.c
@@ -0,0 +1,544 @@
+/*
+ * phy-core.c -- Generic Phy framework.
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.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.
+ *
+ * This program is distributed in the hope that 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/kernel.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
+
+static struct class *phy_class;
+static DEFINE_MUTEX(phy_provider_mutex);
+static LIST_HEAD(phy_provider_list);
+
+static void devm_phy_release(struct device *dev, void *res)
+{
+ struct phy *phy = *(struct phy **)res;
+
+ phy_put(phy);
+}
+
+static void devm_phy_provider_release(struct device *dev, void *res)
+{
+ struct phy_provider *phy_provider = *(struct phy_provider **)res;
+
+ of_phy_provider_unregister(phy_provider);
+}
+
+static void devm_phy_consume(struct device *dev, void *res)
+{
+ struct phy *phy = *(struct phy **)res;
+
+ phy_destroy(phy);
+}
+
+static int devm_phy_match(struct device *dev, void *res, void *match_data)
+{
+ return res = match_data;
+}
+
+static struct phy *phy_lookup(const char *phy_name)
+{
+ struct phy *phy;
+ struct device *dev;
+ struct class_dev_iter iter;
+
+ class_dev_iter_init(&iter, phy_class, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
+ phy = to_phy(dev);
+ if (strcmp(phy->label, phy_name))
+ continue;
+
+ class_dev_iter_exit(&iter);
+ return phy;
+ }
+
+ class_dev_iter_exit(&iter);
+ return ERR_PTR(-ENODEV);
+}
+
+static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
+{
+ struct phy_provider *phy_provider;
+
+ list_for_each_entry(phy_provider, &phy_provider_list, list) {
+ if (phy_provider->dev->of_node = node)
+ return phy_provider;
+ }
+
+ return ERR_PTR(-EPROBE_DEFER);
+}
+
+/**
+ * of_phy_get() - lookup and obtain a reference to a phy by phandle
+ * @dev: device that requests this phy
+ * @index: the index of the phy
+ *
+ * Returns the phy associated with the given phandle value,
+ * after getting a refcount to it or -ENODEV if there is no such phy or
+ * -EPROBE_DEFER if there is a phandle to the phy, but the device is
+ * not yet loaded. This function uses of_xlate call back function provided
+ * while registering the phy_provider to find the phy instance.
+ */
+static struct phy *of_phy_get(struct device *dev, int index)
+{
+ int ret;
+ struct phy_provider *phy_provider;
+ struct phy *phy = NULL;
+ struct of_phandle_args args;
+
+ ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells",
+ index, &args);
+ if (ret) {
+ dev_dbg(dev, "failed to get phy in %s node\n",
+ dev->of_node->full_name);
+ return ERR_PTR(-ENODEV);
+ }
+
+ mutex_lock(&phy_provider_mutex);
+ phy_provider = of_phy_provider_lookup(args.np);
+ if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
+ phy = ERR_PTR(-EPROBE_DEFER);
+ goto err0;
+ }
+
+ phy = phy_provider->of_xlate(phy_provider->dev, &args);
+ module_put(phy_provider->owner);
+
+err0:
+ mutex_unlock(&phy_provider_mutex);
+ of_node_put(args.np);
+
+ return phy;
+}
+
+/**
+ * phy_put() - release the PHY
+ * @phy: the phy returned by phy_get()
+ *
+ * Releases a refcount the caller received from phy_get().
+ */
+void phy_put(struct phy *phy)
+{
+ if (IS_ERR(phy))
+ return;
+
+ module_put(phy->ops->owner);
+ put_device(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_put);
+
+/**
+ * devm_phy_put() - release the PHY
+ * @dev: device that wants to release this phy
+ * @phy: the phy returned by devm_phy_get()
+ *
+ * destroys the devres associated with this phy and invokes phy_put
+ * to release the phy.
+ */
+void devm_phy_put(struct device *dev, struct phy *phy)
+{
+ int r;
+
+ r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
+ dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_phy_put);
+
+/**
+ * of_phy_simple_xlate() - returns the phy instance from phy provider
+ * @dev: the PHY provider device
+ * @args: of_phandle_args (not used here)
+ *
+ * Intended to be used by phy provider for the common case where #phy-cells is
+ * 0. For other cases where #phy-cells is greater than '0', the phy provider
+ * should provide a custom of_xlate function that reads the *args* and returns
+ * the appropriate phy.
+ */
+struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
+ *args)
+{
+ struct phy *phy;
+ struct class_dev_iter iter;
+ struct device_node *node = dev->of_node;
+
+ class_dev_iter_init(&iter, phy_class, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
+ phy = to_phy(dev);
+ if (node != phy->dev.of_node)
+ continue;
+
+ class_dev_iter_exit(&iter);
+ return phy;
+ }
+
+ class_dev_iter_exit(&iter);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(of_phy_simple_xlate);
+
+/**
+ * phy_get() - lookup and obtain a reference to a phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or phy device name
+ * for non-dt case
+ *
+ * Returns the phy driver, after getting a refcount to it; or
+ * -ENODEV if there is no such phy. The caller is responsible for
+ * calling phy_put() to release that count.
+ */
+struct phy *phy_get(struct device *dev, const char *string)
+{
+ int index = 0;
+ struct phy *phy = NULL;
+
+ if (string = NULL) {
+ dev_WARN(dev, "missing string\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (dev->of_node) {
+ index = of_property_match_string(dev->of_node, "phy-names",
+ string);
+ phy = of_phy_get(dev, index);
+ if (IS_ERR(phy)) {
+ dev_WARN(dev, "unable to find phy\n");
+ return phy;
+ }
+ } else {
+ phy = phy_lookup(string);
+ if (IS_ERR(phy)) {
+ dev_WARN(dev, "unable to find phy\n");
+ return phy;
+ }
+ }
+
+ if (!try_module_get(phy->ops->owner))
+ return ERR_PTR(-EPROBE_DEFER);
+
+ get_device(&phy->dev);
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(phy_get);
+
+/**
+ * devm_phy_get() - lookup and obtain a reference to a phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or phy device name
+ * for non-dt case
+ *
+ * Gets the phy using phy_get(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ */
+struct phy *devm_phy_get(struct device *dev, const char *string)
+{
+ struct phy **ptr, *phy;
+
+ ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ phy = phy_get(dev, string);
+ if (!IS_ERR(phy)) {
+ *ptr = phy;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(devm_phy_get);
+
+/**
+ * phy_create() - create a new phy
+ * @dev: device that is creating the new phy
+ * @id: id of the phy
+ * @ops: function pointers for performing phy operations
+ * @label: label given to the phy
+ *
+ * Called to create a phy using phy framework.
+ */
+struct phy *phy_create(struct device *dev, u8 id, const struct phy_ops *ops,
+ const char *label)
+{
+ int ret;
+ struct phy *phy;
+
+ if (!dev) {
+ dev_WARN(dev, "no device provided for PHY\n");
+ ret = -EINVAL;
+ goto err0;
+ }
+
+ phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+ if (!phy) {
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ device_initialize(&phy->dev);
+ mutex_init(&phy->mutex);
+
+ phy->dev.class = phy_class;
+ phy->dev.parent = dev;
+ phy->dev.of_node = dev->of_node;
+ phy->id = id;
+ phy->ops = ops;
+ phy->label = kstrdup(label, GFP_KERNEL);
+
+ ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
+ if (ret)
+ goto err1;
+
+ ret = device_add(&phy->dev);
+ if (ret)
+ goto err1;
+
+ if (pm_runtime_enabled(dev)) {
+ pm_runtime_enable(&phy->dev);
+ pm_runtime_no_callbacks(&phy->dev);
+ }
+
+ return phy;
+
+err1:
+ put_device(&phy->dev);
+ kfree(phy->label);
+ kfree(phy);
+
+err0:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(phy_create);
+
+/**
+ * devm_phy_create() - create a new phy
+ * @dev: device that is creating the new phy
+ * @id: id of the phy
+ * @ops: function pointers for performing phy operations
+ * @label: label given to the phy
+ *
+ * Creates a new PHY device adding it to the PHY class.
+ * While at that, it also associates the device with the phy using devres.
+ * On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ */
+struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label)
+{
+ struct phy **ptr, *phy;
+
+ ptr = devres_alloc(devm_phy_consume, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ phy = phy_create(dev, id, ops, label);
+ if (!IS_ERR(phy)) {
+ *ptr = phy;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(devm_phy_create);
+
+/**
+ * phy_destroy() - destroy the phy
+ * @phy: the phy to be destroyed
+ *
+ * Called to destroy the phy.
+ */
+void phy_destroy(struct phy *phy)
+{
+ pm_runtime_disable(&phy->dev);
+ device_unregister(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_destroy);
+
+/**
+ * devm_phy_destroy() - destroy the PHY
+ * @dev: device that wants to release this phy
+ * @phy: the phy returned by devm_phy_get()
+ *
+ * destroys the devres associated with this phy and invokes phy_destroy
+ * to destroy the phy.
+ */
+void devm_phy_destroy(struct device *dev, struct phy *phy)
+{
+ int r;
+
+ r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
+ dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_phy_destroy);
+
+/**
+ * __of_phy_provider_register() - create/register phy provider with the framework
+ * @dev: struct device of the phy provider
+ * @owner: the module owner containing of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy provider
+ *
+ * Creates struct phy_provider from dev and of_xlate function pointer.
+ * This is used in the case of dt boot for finding the phy instance from
+ * phy provider.
+ */
+struct phy_provider *__of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+{
+ struct phy_provider *phy_provider;
+
+ phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
+ if (!phy_provider)
+ return ERR_PTR(-ENOMEM);
+
+ phy_provider->dev = dev;
+ phy_provider->owner = owner;
+ phy_provider->of_xlate = of_xlate;
+
+ mutex_lock(&phy_provider_mutex);
+ list_add_tail(&phy_provider->list, &phy_provider_list);
+ mutex_unlock(&phy_provider_mutex);
+
+ return phy_provider;
+}
+EXPORT_SYMBOL_GPL(__of_phy_provider_register);
+
+/**
+ * __devm_of_phy_provider_register() - create/register phy provider with the
+ * framework
+ * @dev: struct device of the phy provider
+ * @owner: the module owner containing of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy provider
+ *
+ * Creates struct phy_provider from dev and of_xlate function pointer.
+ * This is used in the case of dt boot for finding the phy instance from
+ * phy provider. While at that, it also associates the device with the
+ * phy provider using devres. On driver detach, release function is invoked
+ * on the devres data, then, devres data is freed.
+ */
+struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+{
+ struct phy_provider **ptr, *phy_provider;
+
+ ptr = devres_alloc(devm_phy_provider_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ phy_provider = __of_phy_provider_register(dev, owner, of_xlate);
+ if (!IS_ERR(phy_provider)) {
+ *ptr = phy_provider;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return phy_provider;
+}
+EXPORT_SYMBOL_GPL(__devm_of_phy_provider_register);
+
+/**
+ * of_phy_provider_unregister() - unregister phy provider from the framework
+ * @phy_provider: phy provider returned by of_phy_provider_register()
+ *
+ * Removes the phy_provider created using of_phy_provider_register().
+ */
+void of_phy_provider_unregister(struct phy_provider *phy_provider)
+{
+ if (IS_ERR(phy_provider))
+ return;
+
+ mutex_lock(&phy_provider_mutex);
+ list_del(&phy_provider->list);
+ kfree(phy_provider);
+ mutex_unlock(&phy_provider_mutex);
+}
+EXPORT_SYMBOL_GPL(of_phy_provider_unregister);
+
+/**
+ * devm_of_phy_provider_unregister() - remove phy provider from the framework
+ * @dev: struct device of the phy provider
+ *
+ * destroys the devres associated with this phy provider and invokes
+ * of_phy_provider_unregister to unregister the phy provider.
+ */
+void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider) {
+ int r;
+
+ r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
+ phy_provider);
+ dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
+
+/**
+ * phy_release() - release the phy
+ * @dev: the dev member within phy
+ *
+ * When the last reference to the device is removed, it is called
+ * from the embedded kobject as release method.
+ */
+static void phy_release(struct device *dev)
+{
+ struct phy *phy;
+
+ phy = to_phy(dev);
+ dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+ kfree(phy->label);
+ kfree(phy);
+}
+
+static int __init phy_core_init(void)
+{
+ phy_class = class_create(THIS_MODULE, "phy");
+ if (IS_ERR(phy_class)) {
+ pr_err("failed to create phy class --> %ld\n",
+ PTR_ERR(phy_class));
+ return PTR_ERR(phy_class);
+ }
+
+ phy_class->dev_release = phy_release;
+
+ return 0;
+}
+module_init(phy_core_init);
+
+static void __exit phy_core_exit(void)
+{
+ class_destroy(phy_class);
+}
+module_exit(phy_core_exit);
+
+MODULE_DESCRIPTION("Generic PHY Framework");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
new file mode 100644
index 0000000..9351a16
--- /dev/null
+++ b/include/linux/phy/phy.h
@@ -0,0 +1,344 @@
+/*
+ * phy.h -- generic phy header file
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#ifndef __DRIVERS_PHY_H
+#define __DRIVERS_PHY_H
+
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/pm_runtime.h>
+
+struct phy;
+
+/**
+ * struct phy_ops - set of function pointers for performing phy operations
+ * @init: operation to be performed for initializing phy
+ * @exit: operation to be performed while exiting
+ * @power_on: powering on the phy
+ * @power_off: powering off the phy
+ * @owner: the module owner containing the ops
+ */
+struct phy_ops {
+ int (*init)(struct phy *phy);
+ int (*exit)(struct phy *phy);
+ int (*power_on)(struct phy *phy);
+ int (*power_off)(struct phy *phy);
+ struct module *owner;
+};
+
+/**
+ * struct phy - represents the phy device
+ * @dev: phy device
+ * @id: id of the phy
+ * @ops: function pointers for performing phy operations
+ * @label: label given to the phy
+ * @mutex: mutex to protect phy_ops
+ * @init_count: used to protect when the PHY is used by multiple consumers
+ * @power_count: used to protect when the PHY is used by multiple consumers
+ */
+struct phy {
+ struct device dev;
+ int id;
+ const struct phy_ops *ops;
+ const char *label;
+ struct mutex mutex;
+ int init_count;
+ int power_count;
+};
+
+/**
+ * struct phy_provider - represents the phy provider
+ * @dev: phy provider device
+ * @owner: the module owner having of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy pointer
+ * @list: to maintain a linked list of PHY providers
+ */
+struct phy_provider {
+ struct device *dev;
+ struct module *owner;
+ struct list_head list;
+ struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args);
+};
+
+#define to_phy(dev) (container_of((dev), struct phy, dev))
+
+#define of_phy_provider_register(dev, xlate) \
+ __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+#define devm_of_phy_provider_register(dev, xlate) \
+ __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+static inline void phy_set_drvdata(struct phy *phy, void *data)
+{
+ dev_set_drvdata(&phy->dev, data);
+}
+
+static inline void *phy_get_drvdata(struct phy *phy)
+{
+ return dev_get_drvdata(&phy->dev);
+}
+
+#if IS_ENABLED(CONFIG_GENERIC_PHY)
+extern struct phy *phy_get(struct device *dev, const char *string);
+extern struct phy *devm_phy_get(struct device *dev, const char *string);
+extern void phy_put(struct phy *phy);
+extern void devm_phy_put(struct device *dev, struct phy *phy);
+extern struct phy *of_phy_simple_xlate(struct device *dev,
+ struct of_phandle_args *args);
+extern struct phy *phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label);
+extern struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label);
+extern void phy_destroy(struct phy *phy);
+extern void devm_phy_destroy(struct device *dev, struct phy *phy);
+extern struct phy_provider *__of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args));
+extern struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args));
+extern void of_phy_provider_unregister(struct phy_provider *phy_provider);
+extern void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider);
+#else
+static inline struct phy *phy_get(struct device *dev, const char *string)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *devm_phy_get(struct device *dev, const char *string)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void phy_put(struct phy *phy)
+{
+}
+
+static inline void devm_phy_put(struct device *dev, struct phy *phy)
+{
+}
+
+static inline struct phy *of_phy_simple_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void phy_destroy(struct phy *phy)
+{
+}
+
+static inline void devm_phy_destroy(struct device *dev, struct phy *phy)
+{
+}
+
+static inline struct phy_provider *__of_phy_provider_register(
+ struct device *dev, struct module *owner, struct phy * (*of_xlate)(
+ struct device *dev, struct of_phandle_args *args))
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy_provider *__devm_of_phy_provider_register(struct device
+ *dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void of_phy_provider_unregister(struct phy_provider *phy_provider)
+{
+}
+
+static inline void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider)
+{
+}
+#endif
+
+static inline int phy_pm_runtime_get(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_get(&phy->dev);
+}
+
+static inline int phy_pm_runtime_get_sync(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_get_sync(&phy->dev);
+}
+
+static inline int phy_pm_runtime_put(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_put(&phy->dev);
+}
+
+static inline int phy_pm_runtime_put_sync(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_put_sync(&phy->dev);
+}
+
+static inline void phy_pm_runtime_allow(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return;
+
+ pm_runtime_allow(&phy->dev);
+}
+
+static inline void phy_pm_runtime_forbid(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return;
+
+ pm_runtime_forbid(&phy->dev);
+}
+
+static inline int phy_init(struct phy *phy)
+{
+ int ret;
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+ return ret;
+
+ mutex_lock(&phy->mutex);
+ if (phy->init_count++ = 0 && phy->ops->init) {
+ ret = phy->ops->init(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy init failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put(phy);
+ return ret;
+}
+
+static inline int phy_exit(struct phy *phy)
+{
+ int ret;
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+ return ret;
+
+ mutex_lock(&phy->mutex);
+ if (--phy->init_count = 0 && phy->ops->exit) {
+ ret = phy->ops->exit(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put(phy);
+ return ret;
+}
+
+static inline int phy_power_on(struct phy *phy)
+{
+ int ret = -ENOTSUPP;
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+ return ret;
+
+ mutex_lock(&phy->mutex);
+ if (phy->power_count++ = 0 && phy->ops->power_on) {
+ ret = phy->ops->power_on(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+
+ return ret;
+}
+
+static inline int phy_power_off(struct phy *phy)
+{
+ int ret = -ENOTSUPP;
+
+ mutex_lock(&phy->mutex);
+ if (--phy->power_count = 0 && phy->ops->power_off) {
+ ret = phy->ops->power_off(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put(phy);
+
+ return ret;
+}
+
+#endif /* __DRIVERS_PHY_H */
--
1.7.10.4
^ permalink raw reply related
* [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1374129984-765-1-git-send-email-kishon@ti.com>
Used the generic PHY framework API to create the PHY. Now the power off and
power on are done in omap_usb_power_off and omap_usb_power_on respectively.
However using the old USB PHY library cannot be completely removed
because OTG is intertwined with PHY and moving to the new framework
will break OTG. Once we have a separate OTG state machine, we
can get rid of the USB PHY library.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
drivers/usb/phy/Kconfig | 1 +
drivers/usb/phy/phy-omap-usb2.c | 45 +++++++++++++++++++++++++++++++++++----
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 3622fff..cc55993 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -75,6 +75,7 @@ config OMAP_CONTROL_USB
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
+ depends on GENERIC_PHY
select OMAP_CONTROL_USB
help
Enable this to support the transceiver that is part of SOC. This
diff --git a/drivers/usb/phy/phy-omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c
index 844ab68..751b30f 100644
--- a/drivers/usb/phy/phy-omap-usb2.c
+++ b/drivers/usb/phy/phy-omap-usb2.c
@@ -28,6 +28,7 @@
#include <linux/pm_runtime.h>
#include <linux/delay.h>
#include <linux/usb/omap_control_usb.h>
+#include <linux/phy/phy.h>
/**
* omap_usb2_set_comparator - links the comparator present in the sytem with
@@ -119,10 +120,36 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
return 0;
}
+static int omap_usb_power_off(struct phy *x)
+{
+ struct omap_usb *phy = phy_get_drvdata(x);
+
+ omap_control_usb_phy_power(phy->control_dev, 0);
+
+ return 0;
+}
+
+static int omap_usb_power_on(struct phy *x)
+{
+ struct omap_usb *phy = phy_get_drvdata(x);
+
+ omap_control_usb_phy_power(phy->control_dev, 1);
+
+ return 0;
+}
+
+static struct phy_ops ops = {
+ .power_on = omap_usb_power_on,
+ .power_off = omap_usb_power_off,
+ .owner = THIS_MODULE,
+};
+
static int omap_usb2_probe(struct platform_device *pdev)
{
struct omap_usb *phy;
+ struct phy *generic_phy;
struct usb_otg *otg;
+ struct phy_provider *phy_provider;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
@@ -144,6 +171,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy->phy.otg = otg;
phy->phy.type = USB_PHY_TYPE_USB2;
+ phy_provider = devm_of_phy_provider_register(phy->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
phy->control_dev = omap_get_control_dev();
if (IS_ERR(phy->control_dev)) {
dev_dbg(&pdev->dev, "Failed to get control device\n");
@@ -159,6 +191,15 @@ static int omap_usb2_probe(struct platform_device *pdev)
otg->start_srp = omap_usb_start_srp;
otg->phy = &phy->phy;
+ platform_set_drvdata(pdev, phy);
+ pm_runtime_enable(phy->dev);
+
+ generic_phy = devm_phy_create(phy->dev, 0, &ops, "omap-usb2");
+ if (IS_ERR(generic_phy))
+ return PTR_ERR(generic_phy);
+
+ phy_set_drvdata(generic_phy, phy);
+
phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
if (IS_ERR(phy->wkupclk)) {
dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
@@ -174,10 +215,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
usb_add_phy_dev(&phy->phy);
- platform_set_drvdata(pdev, phy);
-
- pm_runtime_enable(phy->dev);
-
return 0;
}
--
1.7.10.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox