* [PATCH v2 2/2] arm64: dts: hi6220: add resets property into dwmmc nodes
From: Leo Yan @ 2016-10-28 7:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <d7993c1a-5e50-9a33-0900-5c1a79884d3c@samsung.com>
On Fri, Oct 28, 2016 at 04:33:41PM +0900, Jaehoon Chung wrote:
[...]
> >>> Guodong: Is there any bootloader dependency on that change?
> >>
> >> FYI, I use firmwares available in AOSP
> >
> > I tried latest firmware [1], still cannot boot up until revert the
> > patch "arm64: dts: hi6220: add resets property into dwmmc nodes".
>
> Could you share the log? Is there any log about failure?
Sure, please see below log:
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services and installing virtual address map...
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.9.0-rc1-00251-g323792f (leoy at leoy-linaro) (gcc version 4.9.2 20140904 (prerelease) (crosstool-NG linaro-1.13.1-4.9-2014.09 - Linaro GCC 4.9-2014.09) ) #589 SMP PREEMPT Fri Oct 28 15:35:15 CST 2016
[ 0.000000] Boot CPU: AArch64 Processor [410fd033]
[ 0.000000] efi: Getting EFI parameters from FDT:
[ 0.000000] efi: EFI v2.50 by hikey EFI Oct 26 2016 15:14:29
[ 0.000000] efi: PROP=0x3d8297d8
[ 0.000000] Reserved memory: created CMA memory pool at 0x000000002d000000, size 128 MiB
[ 0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
[ 0.000000] psci: probing for conduit method from DT.
[ 0.000000] psci: PSCIv1.0 detected in firmware.
[ 0.000000] psci: Using standard PSCI v0.2 function IDs
[ 0.000000] psci: MIGRATE_INFO_TYPE not supported.
[ 0.000000] percpu: Embedded 21 pages/cpu @ffff80003df10000 s48000 r8192 d29824 u86016
[ 0.000000] Detected VIPT I-cache on CPU0
[ 0.000000] CPU features: enabling workaround for ARM erratum 845719
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 249229
[ 0.000000] Kernel command line: BOOT_IMAGE=(hd0,gpt6)/Image console=tty0 console=ttyAMA3,115200 root=/dev/disk/by-partlabel/system rootwait rw efi=noruntime
[ 0.000000] log_buf_len individual max cpu contribution: 4096 bytes
[ 0.000000] log_buf_len total cpu_extra contributions: 28672 bytes
[ 0.000000] log_buf_len min size: 16384 bytes
[ 0.000000] log_buf_len: 65536 bytes
[ 0.000000] early log buf free: 14468(88%)
[ 0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.000000] Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes)
[ 0.000000] Inode-cache hash table entries: 65536 (order: 7, 524288 bytes)
[ 0.000000] Memory: 841572K/1012788K available (8316K kernel code, 860K rwdata, 3668K rodata, 1024K init, 283K bss, 40144K reserved, 131072K cma-reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] modules : 0xffff000000000000 - 0xffff000008000000 ( 128 MB)
[ 0.000000] vmalloc : 0xffff000008000000 - 0xffff7dffbfff0000 (129022 GB)
[ 0.000000] .text : 0xffff000008080000 - 0xffff0000088a0000 ( 8320 KB)
[ 0.000000] .rodata : 0xffff0000088a0000 - 0xffff000008c40000 ( 3712 KB)
[ 0.000000] .init : 0xffff000008c40000 - 0xffff000008d40000 ( 1024 KB)
[ 0.000000] .data : 0xffff000008d40000 - 0xffff000008e17200 ( 861 KB)
[ 0.000000] .bss : 0xffff000008e17200 - 0xffff000008e5e0c0 ( 284 KB)
[ 0.000000] fixed : 0xffff7dfffe7fd000 - 0xffff7dfffec00000 ( 4108 KB)
[ 0.000000] PCI I/O : 0xffff7dfffee00000 - 0xffff7dffffe00000 ( 16 MB)
[ 0.000000] vmemmap : 0xffff7e0000000000 - 0xffff800000000000 ( 2048 GB maximum)
[ 0.000000] 0xffff7e0000000000 - 0xffff7e0000f80000 ( 15 MB actual)
[ 0.000000] memory : 0xffff800000000000 - 0xffff80003e000000 ( 992 MB)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] Build-time adjustment of leaf fanout to 64.
[ 0.000000] RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=8.
[ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=8
[ 0.000000] NR_IRQS:64 nr_irqs:64 0
[ 0.000000] GIC: Using split EOI/Deactivate mode
[ 0.000000] arm_arch_timer: Architected cp15 timer(s) running at 1.20MHz (phys).
[ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x11b661f8e, max_idle_ns: 1763180809113 ns
[ 0.000004] sched_clock: 56 bits at 1200kHz, resolution 833ns, wraps every 4398046510838ns
[ 0.000101] clocksource: arm,sp804: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 99544814920 ns
[ 0.000108] sched_clock: 32 bits at 19MHz, resolution 52ns, wraps every 111848106981ns
[ 0.000495] Console: colour dummy device 80x25
[ 0.001193] console [tty0] enabled
[ 0.001224] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.40 BogoMIPS (lpj=4800)
[ 0.001253] pid_max: default: 32768 minimum: 301
[ 0.001331] Security Framework initialized
[ 0.001373] Mount-cache hash table entries: 2048 (order: 2, 16384 bytes)
[ 0.001392] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes)
[ 0.002258] ASID allocator initialised with 65536 entries
[ 0.032726] EFI runtime services will be disabled.
[ 0.080274] Detected VIPT I-cache on CPU1
[ 0.080323] CPU1: Booted secondary processor [410fd033]
[ 0.112299] Detected VIPT I-cache on CPU2
[ 0.112321] CPU2: Booted secondary processor [410fd033]
[ 0.144348] Detected VIPT I-cache on CPU3
[ 0.144369] CPU3: Booted secondary processor [410fd033]
[ 0.176488] Detected VIPT I-cache on CPU4
[ 0.176529] CPU4: Booted secondary processor [410fd033]
[ 0.208479] Detected VIPT I-cache on CPU5
[ 0.208501] CPU5: Booted secondary processor [410fd033]
[ 0.240546] Detected VIPT I-cache on CPU6
[ 0.240568] CPU6: Booted secondary processor [410fd033]
[ 0.272610] Detected VIPT I-cache on CPU7
[ 0.272632] CPU7: Booted secondary processor [410fd033]
[ 0.272708] Brought up 8 CPUs
[ 0.272887] SMP: Total of 8 processors activated.
[ 0.272904] CPU features: detected feature: 32-bit EL0 Support
[ 0.272975] CPU: All CPU(s) started at EL2
[ 0.273028] alternatives: patching kernel code
[ 0.273645] devtmpfs: initialized
[ 0.278919] DMI not present or invalid.
[ 0.279161] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[ 0.282522] pinctrl core: initialized pinctrl subsystem
[ 0.283636] NET: Registered protocol family 16
[ 0.300541] cpuidle: using governor menu
[ 0.301073] vdso: 2 pages (1 code @ ffff0000088a7000, 1 data @ ffff000008d44000)
[ 0.301106] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[ 0.301863] DMA: preallocated 256 KiB pool for atomic allocations
[ 0.302088] Serial: AMBA PL011 UART driver
[ 0.303683] f8015000.uart: ttyAMA0 at MMIO 0xf8015000 (irq = 7, base_baud = 0) is a PL011 rev2
[ 0.304121] uart-pl011 f7111000.uart: could not find pctldev for node /soc/pinmux at f7010000/uart1_pmx_func, deferring probe
[ 0.304340] uart-pl011 f7112000.uart: could not find pctldev for node /soc/pinmux at f7010000/uart2_pmx_func, deferring probe
[ 0.304580] uart-pl011 f7113000.uart: could not find pctldev for node /soc/pinmux at f7010000/uart3_pmx_func, deferring probe
[ 0.310373] hi6220-mbox f7510000.mailbox: Mailbox enabled
[ 0.341400] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[ 0.342257] ACPI: Interpreter disabled.
[ 0.342953] vgaarb: loaded
[ 0.343177] SCSI subsystem initialized
[ 0.343450] ssp-pl022 f7106000.spi: could not find pctldev for node /soc/pinmux at f7010000/spi0_pmx_func, deferring probe
[ 0.343955] usbcore: registered new interface driver usbfs
[ 0.344042] usbcore: registered new interface driver hub
[ 0.344177] usbcore: registered new device driver usb
[ 0.344452] i2c_designware f7100000.i2c: could not find pctldev for node /soc/pinmux at f7010000/i2c0_pmx_func, deferring probe
[ 0.344494] i2c_designware f7101000.i2c: could not find pctldev for node /soc/pinmux at f7010000/i2c1_pmx_func, deferring probe
[ 0.344535] i2c_designware f7102000.i2c: could not find pctldev for node /soc/pinmux at f7010000/i2c2_pmx_func, deferring probe
[ 0.344915] pps_core: LinuxPPS API ver. 1 registered
[ 0.344931] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[ 0.345003] PTP clock support registered
[ 0.345325] dmi: Firmware registration failed.
[ 0.345408] Registered efivars operations
[ 0.345580] Advanced Linux Sound Architecture Driver Initialized.
[ 0.346449] clocksource: Switched to clocksource arch_sys_counter
[ 0.346617] VFS: Disk quotas dquot_6.6.0
[ 0.346670] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[ 0.346935] pnp: PnP ACPI: disabled
[ 0.355325] NET: Registered protocol family 2
[ 0.355797] TCP established hash table entries: 8192 (order: 4, 65536 bytes)
[ 0.355885] TCP bind hash table entries: 8192 (order: 5, 131072 bytes)
[ 0.356026] TCP: Hash tables configured (established 8192 bind 8192)
[ 0.356085] UDP hash table entries: 512 (order: 2, 16384 bytes)
[ 0.356120] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[ 0.356255] NET: Registered protocol family 1
[ 0.356569] RPC: Registered named UNIX socket transport module.
[ 0.356585] RPC: Registered udp transport module.
[ 0.356599] RPC: Registered tcp transport module.
[ 0.356613] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.356791] Unpacking initramfs...
[ 0.497134] Freeing initrd memory: 3576K (ffff8000372d5000 - ffff800037653000)
[ 0.497725] kvm [1]: 8-bit VMID
[ 0.497744] kvm [1]: IDMAP page: 890000
[ 0.497758] kvm [1]: HYP VA range: 800000000000:ffffffffffff
[ 0.498691] kvm [1]: Hyp mode initialized successfully
[ 0.498741] kvm [1]: vgic-v2 at f6804000
[ 0.498936] kvm [1]: vgic interrupt IRQ1
[ 0.498978] kvm [1]: virtual timer IRQ4
[ 0.501267] futex hash table entries: 2048 (order: 6, 262144 bytes)
[ 0.501394] audit: initializing netlink subsys (disabled)
[ 0.501462] audit: type=2000 audit(0.495:1): initialized
[ 0.501845] workingset: timestamp_bits=46 max_order=18 bucket_order=0
[ 0.508960] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 0.509596] NFS: Registering the id_resolver key type
[ 0.509632] Key type id_resolver registered
[ 0.509645] Key type id_legacy registered
[ 0.509665] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[ 0.509833] 9p: Installing v9fs 9p2000 file system support
[ 0.512208] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 247)
[ 0.512235] io scheduler noop registered
[ 0.512349] io scheduler cfq registered (default)
[ 0.513271] libphy: mdio_driver_register: phy-bcm-ns2-pci
[ 0.514198] pinctrl-single f7010000.pinmux: 159 pins at pa ffff000008e81000 size 636
[ 0.514612] pinctrl-single f7010800.pinmux: 163 pins at pa ffff000008e83800 size 652
[ 0.514770] pinctrl-single f8001800.pinmux: 30 pins at pa ffff000008e85800 size 120
[ 0.515809] pl061_gpio f8011000.gpio: PL061 GPIO chip @0x00000000f8011000 registered
[ 0.516214] pl061_gpio f8012000.gpio: PL061 GPIO chip @0x00000000f8012000 registered
[ 0.516610] pl061_gpio f8013000.gpio: PL061 GPIO chip @0x00000000f8013000 registered
[ 0.516687] gpio gpiochip3: gpio-line-names specifies 9 line names but there are 8 lines on the chip
[ 0.517038] pl061_gpio f8014000.gpio: PL061 GPIO chip @0x00000000f8014000 registered
[ 0.517416] pl061_gpio f7020000.gpio: PL061 GPIO chip @0x00000000f7020000 registered
[ 0.517796] pl061_gpio f7021000.gpio: PL061 GPIO chip @0x00000000f7021000 registered
[ 0.518172] pl061_gpio f7022000.gpio: PL061 GPIO chip @0x00000000f7022000 registered
[ 0.518577] pl061_gpio f7023000.gpio: PL061 GPIO chip @0x00000000f7023000 registered
[ 0.518658] gpio gpiochip8: gpio-line-names specifies 9 line names but there are 8 lines on the chip
[ 0.518999] pl061_gpio f7024000.gpio: PL061 GPIO chip @0x00000000f7024000 registered
[ 0.519385] pl061_gpio f7025000.gpio: PL061 GPIO chip @0x00000000f7025000 registered
[ 0.519774] pl061_gpio f7026000.gpio: PL061 GPIO chip @0x00000000f7026000 registered
[ 0.520162] pl061_gpio f7027000.gpio: PL061 GPIO chip @0x00000000f7027000 registered
[ 0.520550] pl061_gpio f7028000.gpio: PL061 GPIO chip @0x00000000f7028000 registered
[ 0.520939] pl061_gpio f7029000.gpio: PL061 GPIO chip @0x00000000f7029000 registered
[ 0.521324] pl061_gpio f702a000.gpio: PL061 GPIO chip @0x00000000f702a000 registered
[ 0.521719] pl061_gpio f702b000.gpio: PL061 GPIO chip @0x00000000f702b000 registered
[ 0.522107] pl061_gpio f702c000.gpio: PL061 GPIO chip @0x00000000f702c000 registered
[ 0.522505] pl061_gpio f702d000.gpio: PL061 GPIO chip @0x00000000f702d000 registered
[ 0.522884] pl061_gpio f702e000.gpio: PL061 GPIO chip @0x00000000f702e000 registered
[ 0.523275] pl061_gpio f702f000.gpio: PL061 GPIO chip @0x00000000f702f000 registered
[ 0.526086] xenfs: not registering filesystem on non-xen platform
[ 0.528934] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[ 0.530124] SuperH (H)SCI(F) driver initialized
[ 0.530364] msm_serial: driver initialized
[ 0.536344] loop: module loaded
[ 0.539526] hisi_sas: driver version v1.6
[ 0.541976] libphy: Fixed MDIO Bus: probed
[ 0.542702] tun: Universal TUN/TAP device driver, 1.6
[ 0.542719] tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
[ 0.543688] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[ 0.543707] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[ 0.543804] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.4.0-k
[ 0.543821] igb: Copyright (c) 2007-2014 Intel Corporation.
[ 0.543906] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.4.0-k
[ 0.543930] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[ 0.544018] sky2: driver version 1.30
[ 0.544551] VFIO - User Level meta-driver version: 0.3
[ 0.546560] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[ 0.546590] ehci-pci: EHCI PCI platform driver
[ 0.546638] ehci-platform: EHCI generic platform driver
[ 0.546730] ehci-exynos: EHCI EXYNOS driver
[ 0.546802] ehci-msm: Qualcomm On-Chip EHCI Host Controller
[ 0.546866] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[ 0.546900] ohci-pci: OHCI PCI platform driver
[ 0.546952] ohci-platform: OHCI generic platform driver
[ 0.547024] ohci-exynos: OHCI EXYNOS driver
[ 0.547324] usbcore: registered new interface driver usb-storage
[ 0.547863] file system registered
[ 0.548183] mousedev: PS/2 mouse device common for all mice
[ 0.548621] input: HISI 65xx PowerOn Key as /devices/platform/f8000000.pmic/hi65xx-powerkey.0.auto/input/input0
[ 0.549253] rtc-pl031 f8003000.rtc: rtc core: registered pl031 as rtc0
[ 0.549459] rtc-pl031 f8004000.rtc: rtc core: registered pl031 as rtc1
[ 0.549796] i2c /dev entries driver
[ 0.552183] sdhci: Secure Digital Host Controller Interface driver
[ 0.552207] sdhci: Copyright(c) Pierre Ossman
[ 0.552403] Synopsys Designware Multimedia Card Interface Driver
[ 0.553405] sdhci-pltfm: SDHCI platform and OF driver helper
[ 0.554851] ledtrig-cpu: registered to indicate activity on CPUs
[ 0.555695] usbcore: registered new interface driver usbhid
[ 0.555717] usbhid: USB HID core driver
[ 0.557233] NET: Registered protocol family 17
[ 0.557320] 9pnet: Installing 9P2000 support
[ 0.557383] Key type dns_resolver registered
[ 0.557996] registered taskstats version 1
[ 0.561690] f7111000.uart: ttyAMA1 at MMIO 0xf7111000 (irq = 8, base_baud = 0) is a PL011 rev2
[ 0.562226] f7112000.uart: ttyAMA2 at MMIO 0xf7112000 (irq = 9, base_baud = 0) is a PL011 rev2
[ 0.562553] f7113000.uart: ttyAMA3 at MMIO 0xf7113000 (irq = 10, base_baud = 0) is a PL011 rev2
[ 1.916968] console [ttyAMA3] enabled
[ 1.922080] ssp-pl022 f7106000.spi: ARM PL022 driver, device ID: 0x00041022
[ 1.929144] ssp-pl022 f7106000.spi: mapped registers from 0x00000000f7106000 to ffff000008f03000
[ 1.938007] ssp-pl022 f7106000.spi: Failed to work in dma mode, work without dma!
[ 1.949535] f72c0000.usb supply vusb_d not found, using dummy regulator
[ 1.956256] f72c0000.usb supply vusb_a not found, using dummy regulator
[ 2.344873] dwc2 f72c0000.usb: EPs: 16, dedicated fifos, 1920 entries in SPRAM
[ 2.353154] dwc2 f72c0000.usb: DWC OTG Controller
[ 2.357891] dwc2 f72c0000.usb: new USB bus registered, assigned bus number 1
[ 2.364979] dwc2 f72c0000.usb: irq 38, io mem 0x00000000
[ 2.371082] hub 1-0:1.0: USB hub found
[ 2.374866] hub 1-0:1.0: 1 port detected
[ 2.382071] rtc-pl031 f8003000.rtc: setting system clock to 1970-01-01 00:00:19 UTC (19)
[ 2.390486] LDO2_2V8: disabling
[ 2.393639] LDO7_SDIO: disabling
[ 2.396900] LDO10_2V85: disabling
[ 2.400234] LDO13_1V8: disabling
[ 2.403476] LDO14_2V8: disabling
[ 2.406721] LDO17_2V5: disabling
[ 2.409956] LDO19_3V0: disabling
[ 2.413199] wlan-en-regulator: disabling
[ 2.417135] ALSA device list:
[ 2.420109] No soundcards found.
[ 2.423712] uart-pl011 f7113000.uart: no DMA platform data
[ 2.429585] Freeing unused kernel memory: 1024K (ffff800000c40000 - ffff800000d40000)
Loading, please wait...
starting version 228
[ 2.479981] random: systemd-udevd: uninitialized urandom read (16 bytes read)
[ 2.483570] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.483680] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.485404] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.485631] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.485859] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.486098] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.486305] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.486729] random: udevadm: uninitialized urandom read (16 bytes read)
[ 2.486951] random: udevadm: uninitialized urandom read (16 bytes read)
Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... modprobe: can't change directory to '4.9.0-rc1-00251-g323792f': No such file or directory
done.
Begin: Waiting for root file system ... Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Thanks,
Leo Yan
^ permalink raw reply
* [PATCH v2 2/2] arm64: dts: hi6220: add resets property into dwmmc nodes
From: Jaehoon Chung @ 2016-10-28 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028072640.GB17266@leoy-linaro>
Hi,
On 10/28/2016 04:26 PM, Leo Yan wrote:
> On Fri, Oct 28, 2016 at 08:43:51AM +0200, Vincent Guittot wrote:
>
> [...]
>
>>> running with? Also do you have any details about the card in case its
>>> card specific?
>>
>> The sdcard is quite common: sandisk ultra 16GB
>> and my rootfs is on the sdcard
>
> I'm using rootfs in emmc also have same failure.
>
>>> Guodong: Is there any bootloader dependency on that change?
>>
>> FYI, I use firmwares available in AOSP
>
> I tried latest firmware [1], still cannot boot up until revert the
> patch "arm64: dts: hi6220: add resets property into dwmmc nodes".
Could you share the log? Is there any log about failure?
Best Regards,
Jaehoon Chung
>
> [1] http://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/
>
> Thanks,
> Leo Yan
>
>
>
^ permalink raw reply
* [PATCH v6 9/9] MAINTAINERS: Update HISILICON DRM entries
From: Rongrong Zou @ 2016-10-28 7:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index c447953..cc5ee3a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4117,6 +4117,7 @@ F: drivers/gpu/drm/gma500/
DRM DRIVERS FOR HISILICON
M: Xinliang Liu <z.liuxinliang@hisilicon.com>
+M: Rongrong Zou <zourongrong@gmail.com>
R: Xinwei Kong <kong.kongxinwei@hisilicon.com>
R: Chen Feng <puck.chen@hisilicon.com>
L: dri-devel at lists.freedesktop.org
--
1.9.1
^ permalink raw reply related
* [PATCH v6 8/9] drm/hisilicon/hibmc: Add vblank interruput
From: Rongrong Zou @ 2016-10-28 7:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Add vblank interrupt.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 56 ++++++++++++++++++++++++-
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 1 +
2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 4253603..b668e3e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -40,16 +40,46 @@
static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
+ struct hibmc_drm_device *hidev =
+ (struct hibmc_drm_device *)dev->dev_private;
+
+ writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(1),
+ hidev->mmio + HIBMC_RAW_INTERRUPT_EN);
+
return 0;
}
static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
{
+ struct hibmc_drm_device *hidev =
+ (struct hibmc_drm_device *)dev->dev_private;
+
+ writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(0),
+ hidev->mmio + HIBMC_RAW_INTERRUPT_EN);
+}
+
+irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
+{
+ struct drm_device *dev = (struct drm_device *)arg;
+ struct hibmc_drm_device *hidev =
+ (struct hibmc_drm_device *)dev->dev_private;
+ struct drm_crtc *crtc = &hidev->crtc;
+ u32 status;
+
+ status = readl(hidev->mmio + HIBMC_RAW_INTERRUPT);
+
+ if (status & HIBMC_RAW_INTERRUPT_VBLANK(1)) {
+ writel(HIBMC_RAW_INTERRUPT_VBLANK(1),
+ hidev->mmio + HIBMC_RAW_INTERRUPT);
+ drm_crtc_handle_vblank(crtc);
+ }
+
+ return IRQ_HANDLED;
}
static struct drm_driver hibmc_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET |
- DRIVER_ATOMIC,
+ DRIVER_ATOMIC | DRIVER_HAVE_IRQ,
.fops = &hibmc_fops,
.name = "hibmc",
.date = "20160828",
@@ -63,6 +93,7 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
.dumb_create = hibmc_dumb_create,
.dumb_map_offset = hibmc_dumb_mmap_offset,
.dumb_destroy = drm_gem_dumb_destroy,
+ .irq_handler = hibmc_drm_interrupt,
};
static int hibmc_pm_suspend(struct device *dev)
@@ -242,6 +273,13 @@ static int hibmc_unload(struct drm_device *dev)
struct hibmc_drm_device *hidev = dev->dev_private;
hibmc_fbdev_fini(hidev);
+
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
+ if (hidev->msi_enabled)
+ pci_disable_msi(dev->pdev);
+ drm_vblank_cleanup(dev);
+
hibmc_kms_fini(hidev);
hibmc_mm_fini(hidev);
hibmc_hw_fini(hidev);
@@ -272,6 +310,22 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
if (ret)
goto err;
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret) {
+ DRM_ERROR("failed to initialize vblank.\n");
+ goto err;
+ }
+
+ hidev->msi_enabled = 0;
+ if (pci_enable_msi(dev->pdev)) {
+ DRM_ERROR("Enabling MSI failed!\n");
+ } else {
+ hidev->msi_enabled = 1;
+ ret = drm_irq_install(dev, dev->pdev->irq);
+ if (ret)
+ DRM_ERROR("install irq failed , ret = %d\n", ret);
+ }
+
/* reset all the states of crtc/plane/encoder/connector */
drm_mode_config_reset(dev);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 450247d..f1706fb 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -42,6 +42,7 @@ struct hibmc_drm_device {
void __iomem *fb_map;
unsigned long fb_base;
unsigned long fb_size;
+ int msi_enabled;
/* drm */
struct drm_device *dev;
--
1.9.1
^ permalink raw reply related
* [PATCH v6 7/9] drm/hisilicon/hibmc: Add connector for VDAC
From: Rongrong Zou @ 2016-10-28 7:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Add connector funcs and helper funcs for VDAC.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 8 +++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 +
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 76 ++++++++++++++++++++++++
3 files changed, 86 insertions(+)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index ba191e1..4253603 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -131,6 +131,14 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
return ret;
}
+ ret = hibmc_connector_init(hidev);
+ if (ret) {
+ DRM_ERROR("failed to init connector\n");
+ return ret;
+ }
+
+ drm_mode_connector_attach_encoder(&hidev->connector,
+ &hidev->encoder);
return 0;
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 401cea4..450247d 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -48,6 +48,7 @@ struct hibmc_drm_device {
struct drm_plane plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
+ struct drm_connector connector;
bool mode_config_initialized;
/* ttm */
@@ -89,6 +90,7 @@ static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
int hibmc_plane_init(struct hibmc_drm_device *hidev);
int hibmc_crtc_init(struct hibmc_drm_device *hidev);
int hibmc_encoder_init(struct hibmc_drm_device *hidev);
+int hibmc_connector_init(struct hibmc_drm_device *hidev);
int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index 953f659..ebefcd1 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -87,3 +87,79 @@ int hibmc_encoder_init(struct hibmc_drm_device *hidev)
drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
return 0;
}
+
+static int hibmc_connector_get_modes(struct drm_connector *connector)
+{
+ int count;
+
+ count = drm_add_modes_noedid(connector, 800, 600);
+ drm_set_preferred_mode(connector, defx, defy);
+ return count;
+}
+
+static int hibmc_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct hibmc_drm_device *hiprivate =
+ container_of(connector, struct hibmc_drm_device, connector);
+ unsigned long size = mode->hdisplay * mode->vdisplay * 4;
+
+ if (size * 2 > hiprivate->fb_size)
+ return MODE_BAD;
+
+ return MODE_OK;
+}
+
+static struct drm_encoder *
+hibmc_connector_best_encoder(struct drm_connector *connector)
+{
+ int enc_id = connector->encoder_ids[0];
+
+ /* pick the encoder ids */
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
+
+ return NULL;
+}
+
+static enum drm_connector_status hibmc_connector_detect(struct drm_connector
+ *connector, bool force)
+{
+ return connector_status_connected;
+}
+
+static const struct drm_connector_helper_funcs
+ hibmc_connector_connector_helper_funcs = {
+ .get_modes = hibmc_connector_get_modes,
+ .mode_valid = hibmc_connector_mode_valid,
+ .best_encoder = hibmc_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs hibmc_connector_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = hibmc_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+int hibmc_connector_init(struct hibmc_drm_device *hidev)
+{
+ struct drm_device *dev = hidev->dev;
+ struct drm_connector *connector = &hidev->connector;
+ int ret;
+
+ ret = drm_connector_init(dev, connector,
+ &hibmc_connector_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA);
+ if (ret) {
+ DRM_ERROR("failed to init connector\n");
+ return ret;
+ }
+ drm_connector_helper_add(connector,
+ &hibmc_connector_connector_helper_funcs);
+
+ return 0;
+}
--
1.9.1
^ permalink raw reply related
* [PATCH v6 6/9] drm/hisilicon/hibmc: Add encoder for VDAC
From: Rongrong Zou @ 2016-10-28 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Add encoder funcs and helpers for VDAC.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +-
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 6 ++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 +
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 89 ++++++++++++++++++++++++
4 files changed, 98 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 72e107e..e04f114 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,5 +1,5 @@
ccflags-y := -Iinclude/drm
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_fbdev.o hibmc_drm_power.o hibmc_ttm.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_fbdev.o hibmc_drm_power.o hibmc_ttm.o
obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o
#obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 303cd36..ba191e1 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -125,6 +125,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
return ret;
}
+ ret = hibmc_encoder_init(hidev);
+ if (ret) {
+ DRM_ERROR("failed to init encoder\n");
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 5731ec2..401cea4 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -47,6 +47,7 @@ struct hibmc_drm_device {
struct drm_device *dev;
struct drm_plane plane;
struct drm_crtc crtc;
+ struct drm_encoder encoder;
bool mode_config_initialized;
/* ttm */
@@ -87,6 +88,7 @@ static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
int hibmc_plane_init(struct hibmc_drm_device *hidev);
int hibmc_crtc_init(struct hibmc_drm_device *hidev);
+int hibmc_encoder_init(struct hibmc_drm_device *hidev);
int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
new file mode 100644
index 0000000..953f659
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -0,0 +1,89 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+static int defx = 800;
+static int defy = 600;
+
+module_param(defx, int, 0444);
+module_param(defy, int, 0444);
+MODULE_PARM_DESC(defx, "default x resolution");
+MODULE_PARM_DESC(defy, "default y resolution");
+
+static void hibmc_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ u32 reg;
+ struct drm_device *dev = encoder->dev;
+ struct hibmc_drm_device *hidev = dev->dev_private;
+
+ /* just open DISPLAY_CONTROL_HISILE register bit 3:0*/
+ reg = readl(hidev->mmio + DISPLAY_CONTROL_HISILE);
+ reg |= 0xf;
+ writel(reg, hidev->mmio + DISPLAY_CONTROL_HISILE);
+}
+
+static int hibmc_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ return 0;
+}
+
+static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
+ .mode_set = hibmc_encoder_mode_set,
+ .disable = hibmc_encoder_disable,
+ .enable = hibmc_encoder_enable,
+ .atomic_check = hibmc_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs hibmc_encoder_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+int hibmc_encoder_init(struct hibmc_drm_device *hidev)
+{
+ struct drm_device *dev = hidev->dev;
+ struct drm_encoder *encoder = &hidev->encoder;
+ int ret;
+
+ encoder->possible_crtcs = 0x1;
+ ret = drm_encoder_init(dev, encoder, &hibmc_encoder_encoder_funcs,
+ DRM_MODE_ENCODER_DAC, NULL);
+ if (ret) {
+ DRM_ERROR("failed to init encoder\n");
+ return ret;
+ }
+
+ drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
+ return 0;
+}
--
1.9.1
^ permalink raw reply related
* [PATCH v6 5/9] drm/hisilicon/hibmc: Add crtc for DE
From: Rongrong Zou @ 2016-10-28 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Add crtc funcs and helper funcs for DE.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 318 ++++++++++++++++++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 6 +
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 +
3 files changed, 326 insertions(+)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index 9c1a68c..9b5d0d0 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -23,6 +23,7 @@
#include "hibmc_drm_drv.h"
#include "hibmc_drm_regs.h"
+#include "hibmc_drm_de.h"
#include "hibmc_drm_power.h"
/* ---------------------------------------------------------------------- */
@@ -168,3 +169,320 @@ int hibmc_plane_init(struct hibmc_drm_device *hidev)
drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
return 0;
}
+
+static void hibmc_crtc_enable(struct drm_crtc *crtc)
+{
+ unsigned int reg;
+ /* power mode 0 is default. */
+ struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+ hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+ reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+ hibmc_set_current_gate(hidev, reg);
+ drm_crtc_vblank_on(crtc);
+}
+
+static void hibmc_crtc_disable(struct drm_crtc *crtc)
+{
+ unsigned int reg;
+ struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+ drm_crtc_vblank_off(crtc);
+
+ hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_SLEEP);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg |= HIBMC_CURR_GATE_LOCALMEM(OFF);
+ reg |= HIBMC_CURR_GATE_DISPLAY(OFF);
+ hibmc_set_current_gate(hidev, reg);
+}
+
+static int hibmc_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ return 0;
+}
+
+static unsigned int format_pll_reg(void)
+{
+ unsigned int pllreg = 0;
+ struct panel_pll pll = {0};
+
+ /* Note that all PLL's have the same format. Here,
+ * we just use Panel PLL parameter to work out the bit
+ * fields in the register.On returning a 32 bit number, the value can
+ * be applied to any PLL in the calling function.
+ */
+ pllreg |= HIBMC_PLL_CTRL_BYPASS(OFF) & HIBMC_PLL_CTRL_BYPASS_MASK;
+ pllreg |= HIBMC_PLL_CTRL_POWER(ON) & HIBMC_PLL_CTRL_POWER_MASK;
+ pllreg |= HIBMC_PLL_CTRL_INPUT(OSC) & HIBMC_PLL_CTRL_INPUT_MASK;
+ pllreg |= HIBMC_PLL_CTRL_POD(pll.POD) & HIBMC_PLL_CTRL_POD_MASK;
+ pllreg |= HIBMC_PLL_CTRL_OD(pll.OD) & HIBMC_PLL_CTRL_OD_MASK;
+ pllreg |= HIBMC_PLL_CTRL_N(pll.N) & HIBMC_PLL_CTRL_N_MASK;
+ pllreg |= HIBMC_PLL_CTRL_M(pll.M) & HIBMC_PLL_CTRL_M_MASK;
+
+ return pllreg;
+}
+
+static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll)
+{
+ unsigned long tmp0, tmp1;
+ struct hibmc_drm_device *hidev = dev->dev_private;
+
+ /* 1. outer_bypass_n=0 */
+ tmp0 = readl(hidev->mmio + CRT_PLL1_HS);
+ tmp0 &= 0xBFFFFFFF;
+ writel(tmp0, hidev->mmio + CRT_PLL1_HS);
+
+ /* 2. pll_pd=1?inter_bypass=1 */
+ writel(0x21000000, hidev->mmio + CRT_PLL1_HS);
+
+ /* 3. config pll */
+ writel(pll, hidev->mmio + CRT_PLL1_HS);
+
+ /* 4. delay */
+ mdelay(1);
+
+ /* 5. pll_pd =0 */
+ tmp1 = pll & ~0x01000000;
+ writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+ /* 6. delay */
+ mdelay(1);
+
+ /* 7. inter_bypass=0 */
+ tmp1 &= ~0x20000000;
+ writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+ /* 8. delay */
+ mdelay(1);
+
+ /* 9. outer_bypass_n=1 */
+ tmp1 |= 0x40000000;
+ writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+}
+
+/* This function takes care the extra registers and bit fields required to
+ *setup a mode in board.
+ *Explanation about Display Control register:
+ *FPGA only supports 7 predefined pixel clocks, and clock select is
+ *in bit 4:0 of new register 0x802a8.
+ */
+static unsigned int display_ctrl_adjust(struct drm_device *dev,
+ struct drm_display_mode *mode,
+ unsigned int ctrl)
+{
+ unsigned long x, y;
+ unsigned long pll1; /* bit[31:0] of PLL */
+ unsigned long pll2; /* bit[63:32] of PLL */
+ struct hibmc_drm_device *hidev = dev->dev_private;
+
+ x = mode->hdisplay;
+ y = mode->vdisplay;
+
+ /* Hisilicon has to set up a new register for PLL control
+ *(CRT_PLL1_HS & CRT_PLL2_HS).
+ */
+ if (x == 800 && y == 600) {
+ pll1 = CRT_PLL1_HS_40MHZ;
+ pll2 = CRT_PLL2_HS_40MHZ;
+ } else if (x == 1024 && y == 768) {
+ pll1 = CRT_PLL1_HS_65MHZ;
+ pll2 = CRT_PLL2_HS_65MHZ;
+ } else if (x == 1152 && y == 864) {
+ pll1 = CRT_PLL1_HS_80MHZ_1152;
+ pll2 = CRT_PLL2_HS_80MHZ;
+ } else if (x == 1280 && y == 768) {
+ pll1 = CRT_PLL1_HS_80MHZ;
+ pll2 = CRT_PLL2_HS_80MHZ;
+ } else if (x == 1280 && y == 720) {
+ pll1 = CRT_PLL1_HS_74MHZ;
+ pll2 = CRT_PLL2_HS_74MHZ;
+ } else if (x == 1280 && y == 960) {
+ pll1 = CRT_PLL1_HS_108MHZ;
+ pll2 = CRT_PLL2_HS_108MHZ;
+ } else if (x == 1280 && y == 1024) {
+ pll1 = CRT_PLL1_HS_108MHZ;
+ pll2 = CRT_PLL2_HS_108MHZ;
+ } else if (x == 1600 && y == 1200) {
+ pll1 = CRT_PLL1_HS_162MHZ;
+ pll2 = CRT_PLL2_HS_162MHZ;
+ } else if (x == 1920 && y == 1080) {
+ pll1 = CRT_PLL1_HS_148MHZ;
+ pll2 = CRT_PLL2_HS_148MHZ;
+ } else if (x == 1920 && y == 1200) {
+ pll1 = CRT_PLL1_HS_193MHZ;
+ pll2 = CRT_PLL2_HS_193MHZ;
+ } else /* default to VGA clock */ {
+ pll1 = CRT_PLL1_HS_25MHZ;
+ pll2 = CRT_PLL2_HS_25MHZ;
+ }
+
+ writel(pll2, hidev->mmio + CRT_PLL2_HS);
+ set_vclock_hisilicon(dev, pll1);
+
+ /* Hisilicon has to set up the top-left and bottom-right
+ * registers as well.
+ * Note that normal chip only use those two register for
+ * auto-centering mode.
+ */
+ writel((HIBMC_CRT_AUTO_CENTERING_TL_TOP(0) &
+ HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK) |
+ (HIBMC_CRT_AUTO_CENTERING_TL_LEFT(0) &
+ HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK),
+ hidev->mmio + HIBMC_CRT_AUTO_CENTERING_TL);
+
+ writel((HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(y - 1) &
+ HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK) |
+ (HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x - 1) &
+ HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK),
+ hidev->mmio + HIBMC_CRT_AUTO_CENTERING_BR);
+
+ /* Assume common fields in ctrl have been properly set before
+ * calling this function.
+ * This function only sets the extra fields in ctrl.
+ */
+
+ /* Set bit 25 of display controller: Select CRT or VGA clock */
+ ctrl &= ~HIBMC_CRT_DISP_CTL_CRTSELECT_MASK;
+ ctrl &= ~HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK;
+
+ ctrl |= HIBMC_CRT_DISP_CTL_CRTSELECT(CRTSELECT_CRT);
+
+ /*ctrl = FIELD_SET(ctrl, HIBMC_CRT_DISP_CTL, CRTSELECT, CRT);*/
+
+ /* Set bit 14 of display controller */
+ /*ctrl &= FIELD_CLEAR(HIBMC_CRT_DISP_CTL, CLOCK_PHASE);*/
+
+ /* clock_phase_polarity is 0 */
+ ctrl |= HIBMC_CRT_DISP_CTL_CLOCK_PHASE(PHASE_ACTIVE_HIGH);
+ /*ctrl = FIELD_SET(ctrl, HIBMC_CRT_DISP_CTL,*/
+ /*CLOCK_PHASE, ACTIVE_HIGH);*/
+
+ writel(ctrl, hidev->mmio + HIBMC_CRT_DISP_CTL);
+
+ return ctrl;
+}
+
+static void hibmc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+ unsigned int val;
+ struct drm_display_mode *mode = &crtc->state->mode;
+ struct drm_device *dev = crtc->dev;
+ struct hibmc_drm_device *hidev = dev->dev_private;
+
+ writel(format_pll_reg(), hidev->mmio + HIBMC_CRT_PLL_CTRL);
+ writel((HIBMC_CRT_HORZ_TOTAL_TOTAL(mode->htotal - 1) &
+ HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK) |
+ (HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(mode->hdisplay - 1) &
+ HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK),
+ hidev->mmio + HIBMC_CRT_HORZ_TOTAL);
+
+ writel((HIBMC_CRT_HORZ_SYNC_WIDTH(mode->hsync_end - mode->hsync_start)
+ & HIBMC_CRT_HORZ_SYNC_WIDTH_MASK) |
+ (HIBMC_CRT_HORZ_SYNC_START(mode->hsync_start - 1)
+ & HIBMC_CRT_HORZ_SYNC_START_MASK),
+ hidev->mmio + HIBMC_CRT_HORZ_SYNC);
+
+ writel((HIBMC_CRT_VERT_TOTAL_TOTAL(mode->vtotal - 1) &
+ HIBMC_CRT_VERT_TOTAL_TOTAL_MASK) |
+ (HIBMC_CRT_VERT_TOTAL_DISPLAY_END(mode->vdisplay - 1) &
+ HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK),
+ hidev->mmio + HIBMC_CRT_VERT_TOTAL);
+
+ writel((HIBMC_CRT_VERT_SYNC_HEIGHT(mode->vsync_end - mode->vsync_start)
+ & HIBMC_CRT_VERT_SYNC_HEIGHT_MASK) |
+ (HIBMC_CRT_VERT_SYNC_START(mode->vsync_start - 1) &
+ HIBMC_CRT_VERT_SYNC_START_MASK),
+ hidev->mmio + HIBMC_CRT_VERT_SYNC);
+
+ val = HIBMC_CRT_DISP_CTL_VSYNC_PHASE(0) &
+ HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK;
+ val |= HIBMC_CRT_DISP_CTL_HSYNC_PHASE(0) &
+ HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK;
+ val |= HIBMC_CRT_DISP_CTL_TIMING(ENABLE);
+ val |= HIBMC_CRT_DISP_CTL_PLANE(ENABLE);
+
+ display_ctrl_adjust(dev, mode, val);
+}
+
+static void hibmc_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ unsigned int reg;
+ struct drm_device *dev = crtc->dev;
+ struct hibmc_drm_device *hidev = dev->dev_private;
+
+ hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+ reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+ hibmc_set_current_gate(hidev, reg);
+
+ /* We can add more initialization as needed. */
+}
+
+static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ if (crtc->state->event)
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ crtc->state->event = NULL;
+
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
+
+/* These provide the minimum set of functions required to handle a CRTC */
+static const struct drm_crtc_funcs hibmc_crtc_funcs = {
+ .page_flip = drm_atomic_helper_page_flip,
+ .set_config = drm_atomic_helper_set_config,
+ .destroy = drm_crtc_cleanup,
+ .reset = drm_atomic_helper_crtc_reset,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
+ .enable = hibmc_crtc_enable,
+ .disable = hibmc_crtc_disable,
+ .mode_set_nofb = hibmc_crtc_mode_set_nofb,
+ .atomic_check = hibmc_crtc_atomic_check,
+ .atomic_begin = hibmc_crtc_atomic_begin,
+ .atomic_flush = hibmc_crtc_atomic_flush,
+};
+
+int hibmc_crtc_init(struct hibmc_drm_device *hidev)
+{
+ struct drm_device *dev = hidev->dev;
+ struct drm_crtc *crtc = &hidev->crtc;
+ struct drm_plane *plane = &hidev->plane;
+ int ret;
+
+ ret = drm_crtc_init_with_planes(dev, crtc, plane,
+ NULL, &hibmc_crtc_funcs, NULL);
+ if (ret) {
+ DRM_ERROR("failed to init crtc.\n");
+ return ret;
+ }
+
+ drm_mode_crtc_set_gamma_size(crtc, 256);
+ drm_crtc_helper_add(crtc, &hibmc_crtc_helper_funcs);
+ return 0;
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 7d96583..303cd36 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -119,6 +119,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
return ret;
}
+ ret = hibmc_crtc_init(hidev);
+ if (ret) {
+ DRM_ERROR("failed to init crtc.\n");
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 49e39d2..5731ec2 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -46,6 +46,7 @@ struct hibmc_drm_device {
/* drm */
struct drm_device *dev;
struct drm_plane plane;
+ struct drm_crtc crtc;
bool mode_config_initialized;
/* ttm */
@@ -85,6 +86,7 @@ static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
int hibmc_plane_init(struct hibmc_drm_device *hidev);
+int hibmc_crtc_init(struct hibmc_drm_device *hidev);
int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
--
1.9.1
^ permalink raw reply related
* [PATCH v6 4/9] drm/hisilicon/hibmc: Add plane for DE
From: Rongrong Zou @ 2016-10-28 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Add plane funcs and helper funcs for DE.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/hibmc/Kconfig | 1 +
drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +-
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 170 ++++++++++++++++++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h | 29 ++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 51 ++++++-
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 5 +
drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 6 +
7 files changed, 261 insertions(+), 3 deletions(-)
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
index bcb8c18..380622a 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -1,6 +1,7 @@
config DRM_HISI_HIBMC
tristate "DRM Support for Hisilicon Hibmc"
depends on DRM && PCI
+ select DRM_KMS_HELPER
select DRM_TTM
help
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 810a37e..72e107e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,5 +1,5 @@
ccflags-y := -Iinclude/drm
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_fbdev.o hibmc_drm_power.o hibmc_ttm.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_fbdev.o hibmc_drm_power.o hibmc_ttm.o
obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o
#obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
new file mode 100644
index 0000000..9c1a68c
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -0,0 +1,170 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+/* ---------------------------------------------------------------------- */
+
+static int hibmc_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_crtc *crtc = state->crtc;
+ struct drm_crtc_state *crtc_state;
+ u32 src_x = state->src_x >> 16;
+ u32 src_y = state->src_y >> 16;
+ u32 src_w = state->src_w >> 16;
+ u32 src_h = state->src_h >> 16;
+ int crtc_x = state->crtc_x;
+ int crtc_y = state->crtc_y;
+ u32 crtc_w = state->crtc_w;
+ u32 crtc_h = state->crtc_h;
+
+ if (!crtc || !fb)
+ return 0;
+
+ crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ if (src_w != crtc_w || src_h != crtc_h) {
+ DRM_ERROR("Scale not support!!!\n");
+ return -EINVAL;
+ }
+
+ if (src_x + src_w > fb->width ||
+ src_y + src_h > fb->height)
+ return -EINVAL;
+
+ if (crtc_x < 0 || crtc_y < 0)
+ return -EINVAL;
+
+ if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
+ crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void hibmc_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct drm_plane_state *state = plane->state;
+ u32 reg;
+ int ret;
+ u64 gpu_addr = 0;
+ unsigned int line_l;
+ struct hibmc_drm_device *hidev =
+ (struct hibmc_drm_device *)plane->dev->dev_private;
+
+ struct hibmc_framebuffer *hibmc_fb;
+ struct hibmc_bo *bo;
+
+ hibmc_fb = to_hibmc_framebuffer(state->fb);
+ bo = gem_to_hibmc_bo(hibmc_fb->obj);
+ ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+ if (ret)
+ return;
+
+ hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
+ if (ret) {
+ ttm_bo_unreserve(&bo->bo);
+ return;
+ }
+
+ ttm_bo_unreserve(&bo->bo);
+
+ writel(gpu_addr, hidev->mmio + HIBMC_CRT_FB_ADDRESS);
+
+ reg = state->fb->width * (state->fb->bits_per_pixel >> 3);
+ /* now line_pad is 16 */
+ reg = PADDING(16, reg);
+
+ line_l = state->fb->width * state->fb->bits_per_pixel / 8;
+ line_l = PADDING(16, line_l);
+ writel((HIBMC_CRT_FB_WIDTH_WIDTH(reg) & HIBMC_CRT_FB_WIDTH_WIDTH_MASK) |
+ (HIBMC_CRT_FB_WIDTH_OFFS(line_l) & HIBMC_CRT_FB_WIDTH_OFFS_MASK),
+ hidev->mmio + HIBMC_CRT_FB_WIDTH);
+
+ /* SET PIXEL FORMAT */
+ reg = readl(hidev->mmio + HIBMC_CRT_DISP_CTL);
+ reg = reg & ~HIBMC_CRT_DISP_CTL_FORMAT_MASK;
+ reg = reg | (HIBMC_CRT_DISP_CTL_FORMAT(state->fb->bits_per_pixel >> 4) &
+ HIBMC_CRT_DISP_CTL_FORMAT_MASK);
+ writel(reg, hidev->mmio + HIBMC_CRT_DISP_CTL);
+}
+
+static void hibmc_plane_atomic_disable(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+}
+
+static const u32 channel_formats1[] = {
+ DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
+ DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888
+};
+
+static struct drm_plane_funcs hibmc_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .set_property = drm_atomic_helper_plane_set_property,
+ .destroy = drm_plane_cleanup,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
+ .atomic_check = hibmc_plane_atomic_check,
+ .atomic_update = hibmc_plane_atomic_update,
+ .atomic_disable = hibmc_plane_atomic_disable,
+};
+
+int hibmc_plane_init(struct hibmc_drm_device *hidev)
+{
+ struct drm_device *dev = hidev->dev;
+ struct drm_plane *plane = &hidev->plane;
+ int ret = 0;
+
+ /*
+ * plane init
+ * TODO: Now only support primary plane, overlay planes
+ * need to do.
+ */
+ ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
+ channel_formats1,
+ ARRAY_SIZE(channel_formats1),
+ DRM_PLANE_TYPE_PRIMARY,
+ NULL);
+ if (ret) {
+ DRM_ERROR("fail to init plane!!!\n");
+ return ret;
+ }
+
+ drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
+ return 0;
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
new file mode 100644
index 0000000..4ce0d7b
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
@@ -0,0 +1,29 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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.
+ *
+ */
+
+#ifndef HIBMC_DRM_DE_H
+#define HIBMC_DRM_DE_H
+
+struct panel_pll {
+ unsigned long M;
+ unsigned long N;
+ unsigned long OD;
+ unsigned long POD;
+};
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 5ac7a7e..7d96583 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/console.h>
+#include <drm/drm_crtc_helper.h>
#include "hibmc_drm_drv.h"
#include "hibmc_drm_regs.h"
@@ -47,8 +48,8 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
}
static struct drm_driver hibmc_driver = {
- .driver_features = DRIVER_GEM,
-
+ .driver_features = DRIVER_GEM | DRIVER_MODESET |
+ DRIVER_ATOMIC,
.fops = &hibmc_fops,
.name = "hibmc",
.date = "20160828",
@@ -70,6 +71,7 @@ static int hibmc_pm_suspend(struct device *dev)
struct drm_device *drm_dev = pci_get_drvdata(pdev);
struct hibmc_drm_device *hidev = drm_dev->dev_private;
+ drm_kms_helper_poll_disable(drm_dev);
drm_fb_helper_set_suspend_unlocked(&hidev->fbdev->helper, 1);
return 0;
@@ -81,7 +83,9 @@ static int hibmc_pm_resume(struct device *dev)
struct drm_device *drm_dev = pci_get_drvdata(pdev);
struct hibmc_drm_device *hidev = drm_dev->dev_private;
+ drm_helper_resume_force_mode(drm_dev);
drm_fb_helper_set_suspend_unlocked(&hidev->fbdev->helper, 0);
+ drm_kms_helper_poll_enable(drm_dev);
return 0;
}
@@ -91,6 +95,41 @@ static int hibmc_pm_resume(struct device *dev)
hibmc_pm_resume)
};
+static int hibmc_kms_init(struct hibmc_drm_device *hidev)
+{
+ int ret;
+
+ drm_mode_config_init(hidev->dev);
+ hidev->mode_config_initialized = true;
+
+ hidev->dev->mode_config.min_width = 0;
+ hidev->dev->mode_config.min_height = 0;
+ hidev->dev->mode_config.max_width = 1920;
+ hidev->dev->mode_config.max_height = 1440;
+
+ hidev->dev->mode_config.fb_base = hidev->fb_base;
+ hidev->dev->mode_config.preferred_depth = 24;
+ hidev->dev->mode_config.prefer_shadow = 0;
+
+ hidev->dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
+
+ ret = hibmc_plane_init(hidev);
+ if (ret) {
+ DRM_ERROR("fail to init plane!!!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void hibmc_kms_fini(struct hibmc_drm_device *hidev)
+{
+ if (hidev->mode_config_initialized) {
+ drm_mode_config_cleanup(hidev->dev);
+ hidev->mode_config_initialized = false;
+ }
+}
+
static int hibmc_hw_config(struct hibmc_drm_device *hidev)
{
unsigned int reg;
@@ -183,6 +222,7 @@ static int hibmc_unload(struct drm_device *dev)
struct hibmc_drm_device *hidev = dev->dev_private;
hibmc_fbdev_fini(hidev);
+ hibmc_kms_fini(hidev);
hibmc_mm_fini(hidev);
hibmc_hw_fini(hidev);
dev->dev_private = NULL;
@@ -208,6 +248,13 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
if (ret)
goto err;
+ ret = hibmc_kms_init(hidev);
+ if (ret)
+ goto err;
+
+ /* reset all the states of crtc/plane/encoder/connector */
+ drm_mode_config_reset(dev);
+
ret = hibmc_fbdev_init(hidev);
if (ret)
goto err;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index a40e9a7..49e39d2 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -45,6 +45,8 @@ struct hibmc_drm_device {
/* drm */
struct drm_device *dev;
+ struct drm_plane plane;
+ bool mode_config_initialized;
/* ttm */
struct {
@@ -82,6 +84,7 @@ static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+int hibmc_plane_init(struct hibmc_drm_device *hidev);
int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
@@ -102,4 +105,6 @@ int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
u32 handle, u64 *offset);
int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
+extern const struct drm_mode_config_funcs hibmc_mode_funcs;
+
#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
index 9822f62..beb4d76 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
@@ -554,3 +554,9 @@ struct hibmc_framebuffer *
}
return &hibmc_fb->fb;
}
+
+const struct drm_mode_config_funcs hibmc_mode_funcs = {
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+ .fb_create = hibmc_user_framebuffer_create,
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v6 3/9] drm/hisilicon/hibmc: Add support for frame buffer
From: Rongrong Zou @ 2016-10-28 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Add support for fbdev and kms fb management.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +-
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 17 ++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 24 ++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 255 ++++++++++++++++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 66 ++++++
5 files changed, 363 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index d5c40b8..810a37e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,5 +1,5 @@
ccflags-y := -Iinclude/drm
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o hibmc_ttm.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_fbdev.o hibmc_drm_power.o hibmc_ttm.o
obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o
#obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 81f4301..5ac7a7e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -66,11 +66,23 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
static int hibmc_pm_suspend(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct hibmc_drm_device *hidev = drm_dev->dev_private;
+
+ drm_fb_helper_set_suspend_unlocked(&hidev->fbdev->helper, 1);
+
return 0;
}
static int hibmc_pm_resume(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct hibmc_drm_device *hidev = drm_dev->dev_private;
+
+ drm_fb_helper_set_suspend_unlocked(&hidev->fbdev->helper, 0);
+
return 0;
}
@@ -170,6 +182,7 @@ static int hibmc_unload(struct drm_device *dev)
{
struct hibmc_drm_device *hidev = dev->dev_private;
+ hibmc_fbdev_fini(hidev);
hibmc_mm_fini(hidev);
hibmc_hw_fini(hidev);
dev->dev_private = NULL;
@@ -195,6 +208,10 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
if (ret)
goto err;
+ ret = hibmc_fbdev_init(hidev);
+ if (ret)
+ goto err;
+
return 0;
err:
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index db8d80e..a40e9a7 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -20,9 +20,22 @@
#define HIBMC_DRM_DRV_H
#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
#include <drm/ttm/ttm_bo_driver.h>
#include <drm/drm_gem.h>
+struct hibmc_framebuffer {
+ struct drm_framebuffer fb;
+ struct drm_gem_object *obj;
+ bool is_fbdev_fb;
+};
+
+struct hibmc_fbdev {
+ struct drm_fb_helper helper;
+ struct hibmc_framebuffer *fb;
+ int size;
+};
+
struct hibmc_drm_device {
/* hw */
void __iomem *mmio;
@@ -41,9 +54,13 @@ struct hibmc_drm_device {
bool initialized;
} ttm;
+ /* fbdev */
+ struct hibmc_fbdev *fbdev;
bool mm_inited;
};
+#define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb)
+
struct hibmc_bo {
struct ttm_buffer_object bo;
struct ttm_placement placement;
@@ -65,8 +82,15 @@ static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
+void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
+
int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
struct drm_gem_object **obj);
+struct hibmc_framebuffer *
+hibmc_framebuffer_init(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj);
int hibmc_mm_init(struct hibmc_drm_device *hibmc);
void hibmc_mm_fini(struct hibmc_drm_device *hibmc);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
new file mode 100644
index 0000000..630124b
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
@@ -0,0 +1,255 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+
+#include "hibmc_drm_drv.h"
+
+/* ---------------------------------------------------------------------- */
+
+static int hibmcfb_create_object(
+ struct hibmc_drm_device *hidev,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object **gobj_p)
+{
+ struct drm_gem_object *gobj;
+ struct drm_device *dev = hidev->dev;
+ u32 size;
+ int ret = 0;
+
+ size = mode_cmd->pitches[0] * mode_cmd->height;
+ ret = hibmc_gem_create(dev, size, true, &gobj);
+ if (ret)
+ return ret;
+
+ *gobj_p = gobj;
+ return ret;
+}
+
+static struct fb_ops hibmc_drm_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = drm_fb_helper_set_par,
+ .fb_fillrect = drm_fb_helper_sys_fillrect,
+ .fb_copyarea = drm_fb_helper_sys_copyarea,
+ .fb_imageblit = drm_fb_helper_sys_imageblit,
+ .fb_pan_display = drm_fb_helper_pan_display,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int hibmc_drm_fb_create(struct drm_fb_helper *helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct hibmc_fbdev *hi_fbdev =
+ container_of(helper, struct hibmc_fbdev, helper);
+ struct hibmc_drm_device *hidev =
+ (struct hibmc_drm_device *)helper->dev->dev_private;
+ struct fb_info *info;
+ struct hibmc_framebuffer *hibmc_fb;
+ struct drm_framebuffer *fb;
+ struct drm_mode_fb_cmd2 mode_cmd;
+ struct drm_gem_object *gobj = NULL;
+ int ret = 0;
+ size_t size;
+ unsigned int bytes_per_pixel;
+ struct hibmc_bo *bo = NULL;
+
+ DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+ sizes->surface_depth = 32;
+
+ bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+ mode_cmd.pitches[0] = mode_cmd.width * bytes_per_pixel;
+ mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+ sizes->surface_depth);
+
+ size = roundup(mode_cmd.pitches[0] * mode_cmd.height, PAGE_SIZE);
+
+ ret = hibmcfb_create_object(hidev, &mode_cmd, &gobj);
+ if (ret) {
+ DRM_ERROR("failed to create fbcon backing object %d\r\n", ret);
+ return -ENOMEM;
+ }
+
+ bo = gem_to_hibmc_bo(gobj);
+
+ ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+ if (ret)
+ return ret;
+
+ ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+ if (ret) {
+ DRM_ERROR("failed to pin fbcon\n");
+ return ret;
+ }
+
+ ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+
+ if (ret) {
+ DRM_ERROR("failed to kmap fbcon\n");
+ ttm_bo_unreserve(&bo->bo);
+ return ret;
+ }
+
+ ttm_bo_unreserve(&bo->bo);
+
+ info = drm_fb_helper_alloc_fbi(helper);
+ if (IS_ERR(info))
+ return PTR_ERR(info);
+
+ info->par = hi_fbdev;
+
+ hibmc_fb = hibmc_framebuffer_init(hidev->dev, &mode_cmd, gobj);
+ if (IS_ERR(hibmc_fb)) {
+ drm_fb_helper_release_fbi(helper);
+ return PTR_ERR(hibmc_fb);
+ }
+
+ hi_fbdev->fb = hibmc_fb;
+ hidev->fbdev->size = size;
+ fb = &hibmc_fb->fb;
+ if (!fb) {
+ DRM_INFO("fb is NULL\n");
+ return -EINVAL;
+ }
+
+ hi_fbdev->helper.fb = fb;
+
+ strcpy(info->fix.id, "hibmcdrmfb");
+
+ info->flags = FBINFO_DEFAULT;
+ info->fbops = &hibmc_drm_fb_ops;
+
+ drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+ drm_fb_helper_fill_var(info, &hidev->fbdev->helper, sizes->fb_width,
+ sizes->fb_height);
+
+ info->screen_base = bo->kmap.virtual;
+ info->screen_size = size;
+
+ info->fix.smem_start = bo->bo.mem.bus.offset + bo->bo.mem.bus.base;
+ info->fix.smem_len = size;
+
+ return 0;
+}
+
+static void hibmc_fbdev_destroy(struct hibmc_fbdev *fbdev)
+{
+ struct hibmc_framebuffer *gfb = fbdev->fb;
+ struct drm_fb_helper *fbh = &fbdev->helper;
+
+ DRM_DEBUG_DRIVER("hibmc_fbdev_destroy\n");
+
+ drm_fb_helper_unregister_fbi(fbh);
+ drm_fb_helper_release_fbi(fbh);
+
+ drm_fb_helper_fini(fbh);
+
+ if (gfb)
+ drm_framebuffer_unreference(&gfb->fb);
+
+ kfree(fbdev);
+}
+
+static const struct drm_fb_helper_funcs hibmc_fbdev_helper_funcs = {
+ .fb_probe = hibmc_drm_fb_create,
+};
+
+int hibmc_fbdev_init(struct hibmc_drm_device *hidev)
+{
+ int ret;
+ struct fb_var_screeninfo *var;
+ struct fb_fix_screeninfo *fix;
+ struct hibmc_fbdev *hifbdev;
+
+ hifbdev = kzalloc(sizeof(*hifbdev), GFP_KERNEL);
+ if (!hifbdev)
+ return -ENOMEM;
+
+ hidev->fbdev = hifbdev;
+ drm_fb_helper_prepare(hidev->dev, &hifbdev->helper,
+ &hibmc_fbdev_helper_funcs);
+
+ /* Now just one crtc and one channel */
+ ret = drm_fb_helper_init(hidev->dev,
+ &hifbdev->helper, 1, 1);
+
+ if (ret)
+ return ret;
+
+ ret = drm_fb_helper_single_add_all_connectors(&hifbdev->helper);
+ if (ret)
+ goto fini;
+
+ ret = drm_fb_helper_initial_config(&hifbdev->helper, 16);
+ if (ret)
+ goto fini;
+
+ var = &hifbdev->helper.fbdev->var;
+ fix = &hifbdev->helper.fbdev->fix;
+
+ DRM_DEBUG("Member of info->var is :\n"
+ "xres=%d\n"
+ "yres=%d\n"
+ "xres_virtual=%d\n"
+ "yres_virtual=%d\n"
+ "xoffset=%d\n"
+ "yoffset=%d\n"
+ "bits_per_pixel=%d\n"
+ "...\n", var->xres, var->yres, var->xres_virtual,
+ var->yres_virtual, var->xoffset, var->yoffset,
+ var->bits_per_pixel);
+ DRM_DEBUG("Member of info->fix is :\n"
+ "smem_start=%lx\n"
+ "smem_len=%d\n"
+ "type=%d\n"
+ "type_aux=%d\n"
+ "visual=%d\n"
+ "xpanstep=%d\n"
+ "ypanstep=%d\n"
+ "ywrapstep=%d\n"
+ "line_length=%d\n"
+ "accel=%d\n"
+ "capabilities=%d\n"
+ "...\n", fix->smem_start, fix->smem_len, fix->type,
+ fix->type_aux, fix->visual, fix->xpanstep,
+ fix->ypanstep, fix->ywrapstep, fix->line_length,
+ fix->accel, fix->capabilities);
+
+ return 0;
+
+fini:
+ drm_fb_helper_fini(&hifbdev->helper);
+ return ret;
+}
+
+void hibmc_fbdev_fini(struct hibmc_drm_device *hidev)
+{
+ if (!hidev->fbdev)
+ return;
+
+ hibmc_fbdev_destroy(hidev->fbdev);
+ hidev->fbdev = NULL;
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
index 0802ebd..9822f62 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
@@ -488,3 +488,69 @@ int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
drm_gem_object_unreference_unlocked(obj);
return 0;
}
+
+/* ---------------------------------------------------------------------- */
+
+static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+ struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb);
+
+ drm_gem_object_unreference_unlocked(hibmc_fb->obj);
+ drm_framebuffer_cleanup(fb);
+ kfree(hibmc_fb);
+}
+
+static const struct drm_framebuffer_funcs hibmc_fb_funcs = {
+ .destroy = hibmc_user_framebuffer_destroy,
+};
+
+struct hibmc_framebuffer *
+hibmc_framebuffer_init(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj)
+{
+ struct hibmc_framebuffer *hibmc_fb;
+ int ret;
+
+ hibmc_fb = kzalloc(sizeof(*hibmc_fb), GFP_KERNEL);
+ if (!hibmc_fb)
+ return ERR_PTR(-ENOMEM);
+
+ drm_helper_mode_fill_fb_struct(&hibmc_fb->fb, mode_cmd);
+ hibmc_fb->obj = obj;
+ ret = drm_framebuffer_init(dev, &hibmc_fb->fb, &hibmc_fb_funcs);
+ if (ret) {
+ DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+ kfree(hibmc_fb);
+ return ERR_PTR(ret);
+ }
+
+ return hibmc_fb;
+}
+
+static struct drm_framebuffer *
+hibmc_user_framebuffer_create(struct drm_device *dev,
+ struct drm_file *filp,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ struct drm_gem_object *obj;
+ struct hibmc_framebuffer *hibmc_fb;
+
+ DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n",
+ mode_cmd->width, mode_cmd->height,
+ (mode_cmd->pixel_format) & 0xff,
+ (mode_cmd->pixel_format >> 8) & 0xff,
+ (mode_cmd->pixel_format >> 16) & 0xff,
+ (mode_cmd->pixel_format >> 24) & 0xff);
+
+ obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
+ if (!obj)
+ return ERR_PTR(-ENOENT);
+
+ hibmc_fb = hibmc_framebuffer_init(dev, mode_cmd, obj);
+ if (IS_ERR(hibmc_fb)) {
+ drm_gem_object_unreference_unlocked(obj);
+ return ERR_PTR((long)hibmc_fb);
+ }
+ return &hibmc_fb->fb;
+}
--
1.9.1
^ permalink raw reply related
* [PATCH v6 2/9] drm/hisilicon/hibmc: Add video memory management
From: Rongrong Zou @ 2016-10-28 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Hibmc have 32m video memory which can be accessed through PCIe by host,
we use ttm to manage these memory.
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/hibmc/Kconfig | 1 +
drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +-
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 12 +
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 46 +++
drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 490 ++++++++++++++++++++++++
5 files changed, 550 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
index a9af90d..bcb8c18 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -1,6 +1,7 @@
config DRM_HISI_HIBMC
tristate "DRM Support for Hisilicon Hibmc"
depends on DRM && PCI
+ select DRM_TTM
help
Choose this option if you have a Hisilicon Hibmc soc chipset.
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 97cf4a0..d5c40b8 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,5 +1,5 @@
ccflags-y := -Iinclude/drm
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o hibmc_ttm.o
obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o
#obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 4669d42..81f4301 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -31,6 +31,7 @@
#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
#endif
+ .mmap = hibmc_mmap,
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
@@ -46,6 +47,8 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
}
static struct drm_driver hibmc_driver = {
+ .driver_features = DRIVER_GEM,
+
.fops = &hibmc_fops,
.name = "hibmc",
.date = "20160828",
@@ -55,6 +58,10 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
.get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = hibmc_enable_vblank,
.disable_vblank = hibmc_disable_vblank,
+ .gem_free_object_unlocked = hibmc_gem_free_object,
+ .dumb_create = hibmc_dumb_create,
+ .dumb_map_offset = hibmc_dumb_mmap_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
};
static int hibmc_pm_suspend(struct device *dev)
@@ -163,6 +170,7 @@ static int hibmc_unload(struct drm_device *dev)
{
struct hibmc_drm_device *hidev = dev->dev_private;
+ hibmc_mm_fini(hidev);
hibmc_hw_fini(hidev);
dev->dev_private = NULL;
return 0;
@@ -183,6 +191,10 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
if (ret)
goto err;
+ ret = hibmc_mm_init(hidev);
+ if (ret)
+ goto err;
+
return 0;
err:
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 0037341..db8d80e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -20,6 +20,8 @@
#define HIBMC_DRM_DRV_H
#include <drm/drmP.h>
+#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/drm_gem.h>
struct hibmc_drm_device {
/* hw */
@@ -30,6 +32,50 @@ struct hibmc_drm_device {
/* drm */
struct drm_device *dev;
+
+ /* ttm */
+ struct {
+ struct drm_global_reference mem_global_ref;
+ struct ttm_bo_global_ref bo_global_ref;
+ struct ttm_bo_device bdev;
+ bool initialized;
+ } ttm;
+
+ bool mm_inited;
};
+struct hibmc_bo {
+ struct ttm_buffer_object bo;
+ struct ttm_placement placement;
+ struct ttm_bo_kmap_obj kmap;
+ struct drm_gem_object gem;
+ struct ttm_place placements[3];
+ int pin_count;
+};
+
+static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo)
+{
+ return container_of(bo, struct hibmc_bo, bo);
+}
+
+static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
+{
+ return container_of(gem, struct hibmc_bo, gem);
+}
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+ struct drm_gem_object **obj);
+
+int hibmc_mm_init(struct hibmc_drm_device *hibmc);
+void hibmc_mm_fini(struct hibmc_drm_device *hibmc);
+int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr);
+void hibmc_gem_free_object(struct drm_gem_object *obj);
+int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+ u32 handle, u64 *offset);
+int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
+
#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
new file mode 100644
index 0000000..0802ebd
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
@@ -0,0 +1,490 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include "hibmc_drm_drv.h"
+#include <ttm/ttm_page_alloc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+static inline struct hibmc_drm_device *
+hibmc_bdev(struct ttm_bo_device *bd)
+{
+ return container_of(bd, struct hibmc_drm_device, ttm.bdev);
+}
+
+static int
+hibmc_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+ return ttm_mem_global_init(ref->object);
+}
+
+static void
+hibmc_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+ ttm_mem_global_release(ref->object);
+}
+
+static int hibmc_ttm_global_init(struct hibmc_drm_device *hibmc)
+{
+ struct drm_global_reference *global_ref;
+ int r;
+
+ global_ref = &hibmc->ttm.mem_global_ref;
+ global_ref->global_type = DRM_GLOBAL_TTM_MEM;
+ global_ref->size = sizeof(struct ttm_mem_global);
+ global_ref->init = &hibmc_ttm_mem_global_init;
+ global_ref->release = &hibmc_ttm_mem_global_release;
+ r = drm_global_item_ref(global_ref);
+ if (r != 0) {
+ DRM_ERROR("Failed setting up TTM memory accounting subsystem.\n"
+ );
+ return r;
+ }
+
+ hibmc->ttm.bo_global_ref.mem_glob =
+ hibmc->ttm.mem_global_ref.object;
+ global_ref = &hibmc->ttm.bo_global_ref.ref;
+ global_ref->global_type = DRM_GLOBAL_TTM_BO;
+ global_ref->size = sizeof(struct ttm_bo_global);
+ global_ref->init = &ttm_bo_global_init;
+ global_ref->release = &ttm_bo_global_release;
+ r = drm_global_item_ref(global_ref);
+ if (r != 0) {
+ DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+ drm_global_item_unref(&hibmc->ttm.mem_global_ref);
+ return r;
+ }
+ return 0;
+}
+
+static void
+hibmc_ttm_global_release(struct hibmc_drm_device *hibmc)
+{
+ if (!hibmc->ttm.mem_global_ref.release)
+ return;
+
+ drm_global_item_unref(&hibmc->ttm.bo_global_ref.ref);
+ drm_global_item_unref(&hibmc->ttm.mem_global_ref);
+ hibmc->ttm.mem_global_ref.release = NULL;
+}
+
+static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo)
+{
+ struct hibmc_bo *bo;
+
+ bo = container_of(tbo, struct hibmc_bo, bo);
+
+ drm_gem_object_release(&bo->gem);
+ kfree(bo);
+}
+
+static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo)
+{
+ if (bo->destroy == &hibmc_bo_ttm_destroy)
+ return true;
+ return false;
+}
+
+static int
+hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
+ struct ttm_mem_type_manager *man)
+{
+ switch (type) {
+ case TTM_PL_SYSTEM:
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+ man->available_caching = TTM_PL_MASK_CACHING;
+ man->default_caching = TTM_PL_FLAG_CACHED;
+ break;
+ case TTM_PL_VRAM:
+ man->func = &ttm_bo_manager_func;
+ man->flags = TTM_MEMTYPE_FLAG_FIXED |
+ TTM_MEMTYPE_FLAG_MAPPABLE;
+ man->available_caching = TTM_PL_FLAG_UNCACHED |
+ TTM_PL_FLAG_WC;
+ man->default_caching = TTM_PL_FLAG_WC;
+ break;
+ default:
+ DRM_ERROR("Unsupported memory type %u\n", type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void hibmc_ttm_placement(struct hibmc_bo *bo, int domain)
+{
+ u32 c = 0;
+ u32 i;
+
+ bo->placement.placement = bo->placements;
+ bo->placement.busy_placement = bo->placements;
+ if (domain & TTM_PL_FLAG_VRAM)
+ bo->placements[c++].flags = TTM_PL_FLAG_WC |
+ TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
+ if (domain & TTM_PL_FLAG_SYSTEM)
+ bo->placements[c++].flags = TTM_PL_MASK_CACHING |
+ TTM_PL_FLAG_SYSTEM;
+ if (!c)
+ bo->placements[c++].flags = TTM_PL_MASK_CACHING |
+ TTM_PL_FLAG_SYSTEM;
+
+ bo->placement.num_placement = c;
+ bo->placement.num_busy_placement = c;
+ for (i = 0; i < c; ++i) {
+ bo->placements[i].fpfn = 0;
+ bo->placements[i].lpfn = 0;
+ }
+}
+
+static void
+hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+ struct hibmc_bo *hibmcbo = hibmc_bo(bo);
+
+ if (!hibmc_ttm_bo_is_hibmc_bo(bo))
+ return;
+
+ hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM);
+ *pl = hibmcbo->placement;
+}
+
+static int hibmc_bo_verify_access(struct ttm_buffer_object *bo,
+ struct file *filp)
+{
+ struct hibmc_bo *hibmcbo = hibmc_bo(bo);
+
+ return drm_vma_node_verify_access(&hibmcbo->gem.vma_node,
+ filp->private_data);
+}
+
+static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
+ struct ttm_mem_reg *mem)
+{
+ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+ struct hibmc_drm_device *hibmc = hibmc_bdev(bdev);
+
+ mem->bus.addr = NULL;
+ mem->bus.offset = 0;
+ mem->bus.size = mem->num_pages << PAGE_SHIFT;
+ mem->bus.base = 0;
+ mem->bus.is_iomem = false;
+ if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+ return -EINVAL;
+ switch (mem->mem_type) {
+ case TTM_PL_SYSTEM:
+ /* system memory */
+ return 0;
+ case TTM_PL_VRAM:
+ mem->bus.offset = mem->start << PAGE_SHIFT;
+ mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0);
+ mem->bus.is_iomem = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void hibmc_ttm_io_mem_free(struct ttm_bo_device *bdev,
+ struct ttm_mem_reg *mem)
+{
+}
+
+static void hibmc_ttm_backend_destroy(struct ttm_tt *tt)
+{
+ ttm_tt_fini(tt);
+ kfree(tt);
+}
+
+static struct ttm_backend_func hibmc_tt_backend_func = {
+ .destroy = &hibmc_ttm_backend_destroy,
+};
+
+static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_bo_device *bdev,
+ unsigned long size,
+ u32 page_flags,
+ struct page *dummy_read_page)
+{
+ struct ttm_tt *tt;
+
+ tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+ if (!tt)
+ return NULL;
+ tt->func = &hibmc_tt_backend_func;
+ if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
+ kfree(tt);
+ return NULL;
+ }
+ return tt;
+}
+
+static int hibmc_ttm_tt_populate(struct ttm_tt *ttm)
+{
+ return ttm_pool_populate(ttm);
+}
+
+static void hibmc_ttm_tt_unpopulate(struct ttm_tt *ttm)
+{
+ ttm_pool_unpopulate(ttm);
+}
+
+struct ttm_bo_driver hibmc_bo_driver = {
+ .ttm_tt_create = hibmc_ttm_tt_create,
+ .ttm_tt_populate = hibmc_ttm_tt_populate,
+ .ttm_tt_unpopulate = hibmc_ttm_tt_unpopulate,
+ .init_mem_type = hibmc_bo_init_mem_type,
+ .evict_flags = hibmc_bo_evict_flags,
+ .move = NULL,
+ .verify_access = hibmc_bo_verify_access,
+ .io_mem_reserve = &hibmc_ttm_io_mem_reserve,
+ .io_mem_free = &hibmc_ttm_io_mem_free,
+ .lru_tail = &ttm_bo_default_lru_tail,
+ .swap_lru_tail = &ttm_bo_default_swap_lru_tail,
+};
+
+int hibmc_mm_init(struct hibmc_drm_device *hibmc)
+{
+ int ret;
+ struct drm_device *dev = hibmc->dev;
+ struct ttm_bo_device *bdev = &hibmc->ttm.bdev;
+
+ ret = hibmc_ttm_global_init(hibmc);
+ if (ret)
+ return ret;
+
+ ret = ttm_bo_device_init(&hibmc->ttm.bdev,
+ hibmc->ttm.bo_global_ref.ref.object,
+ &hibmc_bo_driver,
+ dev->anon_inode->i_mapping,
+ DRM_FILE_PAGE_OFFSET,
+ true);
+ if (ret) {
+ DRM_ERROR("Error initialising bo driver; %d\n", ret);
+ return ret;
+ }
+
+ ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
+ hibmc->fb_size >> PAGE_SHIFT);
+ if (ret) {
+ DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
+ return ret;
+ }
+
+ hibmc->mm_inited = true;
+ return 0;
+}
+
+void hibmc_mm_fini(struct hibmc_drm_device *hibmc)
+{
+ if (!hibmc->mm_inited)
+ return;
+
+ ttm_bo_device_release(&hibmc->ttm.bdev);
+ hibmc_ttm_global_release(hibmc);
+ hibmc->mm_inited = false;
+}
+
+int hibmc_bo_create(struct drm_device *dev, int size, int align,
+ u32 flags, struct hibmc_bo **phibmcbo)
+{
+ struct hibmc_drm_device *hibmc = dev->dev_private;
+ struct hibmc_bo *hibmcbo;
+ size_t acc_size;
+ int ret;
+
+ hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL);
+ if (!hibmcbo)
+ return -ENOMEM;
+
+ ret = drm_gem_object_init(dev, &hibmcbo->gem, size);
+ if (ret) {
+ kfree(hibmcbo);
+ return ret;
+ }
+
+ hibmcbo->bo.bdev = &hibmc->ttm.bdev;
+
+ hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
+
+ acc_size = ttm_bo_dma_acc_size(&hibmc->ttm.bdev, size,
+ sizeof(struct hibmc_bo));
+
+ ret = ttm_bo_init(&hibmc->ttm.bdev, &hibmcbo->bo, size,
+ ttm_bo_type_device, &hibmcbo->placement,
+ align >> PAGE_SHIFT, false, NULL, acc_size,
+ NULL, NULL, hibmc_bo_ttm_destroy);
+ if (ret)
+ return ret;
+
+ *phibmcbo = hibmcbo;
+ return 0;
+}
+
+static inline u64 hibmc_bo_gpu_offset(struct hibmc_bo *bo)
+{
+ return bo->bo.offset;
+}
+
+int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr)
+{
+ int i, ret;
+
+ if (bo->pin_count) {
+ bo->pin_count++;
+ if (gpu_addr)
+ *gpu_addr = hibmc_bo_gpu_offset(bo);
+ }
+
+ hibmc_ttm_placement(bo, pl_flag);
+ for (i = 0; i < bo->placement.num_placement; i++)
+ bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+ ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+ if (ret)
+ return ret;
+
+ bo->pin_count = 1;
+ if (gpu_addr)
+ *gpu_addr = hibmc_bo_gpu_offset(bo);
+ return 0;
+}
+
+int hibmc_bo_push_sysram(struct hibmc_bo *bo)
+{
+ int i, ret;
+
+ if (!bo->pin_count) {
+ DRM_ERROR("unpin bad %p\n", bo);
+ return 0;
+ }
+ bo->pin_count--;
+ if (bo->pin_count)
+ return 0;
+
+ if (bo->kmap.virtual)
+ ttm_bo_kunmap(&bo->kmap);
+
+ hibmc_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
+ for (i = 0; i < bo->placement.num_placement ; i++)
+ bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+
+ ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+ if (ret) {
+ DRM_ERROR("pushing to VRAM failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+int hibmc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_file *file_priv;
+ struct hibmc_drm_device *hibmc;
+
+ if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
+ return -EINVAL;
+
+ file_priv = filp->private_data;
+ hibmc = file_priv->minor->dev->dev_private;
+ return ttm_bo_mmap(filp, vma, &hibmc->ttm.bdev);
+}
+
+int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+ struct drm_gem_object **obj)
+{
+ struct hibmc_bo *hibmcbo;
+ int ret;
+
+ *obj = NULL;
+
+ size = PAGE_ALIGN(size);
+ if (size == 0)
+ return -EINVAL;
+
+ ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo);
+ if (ret) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("failed to allocate GEM object\n");
+ return ret;
+ }
+ *obj = &hibmcbo->gem;
+ return 0;
+}
+
+int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
+{
+ struct drm_gem_object *gobj;
+ u32 handle;
+ int ret;
+
+ args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 16);
+ args->size = args->pitch * args->height;
+
+ ret = hibmc_gem_create(dev, args->size, false,
+ &gobj);
+ if (ret)
+ return ret;
+
+ ret = drm_gem_handle_create(file, gobj, &handle);
+ drm_gem_object_unreference_unlocked(gobj);
+ if (ret)
+ return ret;
+
+ args->handle = handle;
+ return 0;
+}
+
+static void hibmc_bo_unref(struct hibmc_bo **bo)
+{
+ struct ttm_buffer_object *tbo;
+
+ if ((*bo) == NULL)
+ return;
+
+ tbo = &((*bo)->bo);
+ ttm_bo_unref(&tbo);
+ *bo = NULL;
+}
+
+void hibmc_gem_free_object(struct drm_gem_object *obj)
+{
+ struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj);
+
+ hibmc_bo_unref(&hibmcbo);
+}
+
+static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo)
+{
+ return drm_vma_node_offset_addr(&bo->bo.vma_node);
+}
+
+int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+ u32 handle, u64 *offset)
+{
+ struct drm_gem_object *obj;
+ struct hibmc_bo *bo;
+
+ obj = drm_gem_object_lookup(file, handle);
+ if (!obj)
+ return -ENOENT;
+
+ bo = gem_to_hibmc_bo(obj);
+ *offset = hibmc_bo_mmap_offset(bo);
+
+ drm_gem_object_unreference_unlocked(obj);
+ return 0;
+}
--
1.9.1
^ permalink raw reply related
* [PATCH v6 1/9] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
From: Rongrong Zou @ 2016-10-28 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477639682-22520-1-git-send-email-zourongrong@gmail.com>
Add DRM master driver for Hisilicon Hibmc SoC which used for
Out-of-band management. Blow is the general hardware connection,
both the Hibmc and the host CPU are on the same mother board.
+----------+ +----------+
| | PCIe | Hibmc |
|host CPU( |<----->| display |
|arm64,x86)| |subsystem |
+----------+ +----------+
Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
---
drivers/gpu/drm/hisilicon/Kconfig | 1 +
drivers/gpu/drm/hisilicon/Makefile | 1 +
drivers/gpu/drm/hisilicon/hibmc/Kconfig | 7 +
drivers/gpu/drm/hisilicon/hibmc/Makefile | 5 +
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 269 ++++++++++++++++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 35 +++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c | 85 +++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h | 28 +++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h | 212 +++++++++++++++++
9 files changed, 643 insertions(+)
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
index 558c61b..2fd2724 100644
--- a/drivers/gpu/drm/hisilicon/Kconfig
+++ b/drivers/gpu/drm/hisilicon/Kconfig
@@ -2,4 +2,5 @@
# hisilicon drm device configuration.
# Please keep this list sorted alphabetically
+source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
index e3f6d49..c8155bf 100644
--- a/drivers/gpu/drm/hisilicon/Makefile
+++ b/drivers/gpu/drm/hisilicon/Makefile
@@ -2,4 +2,5 @@
# Makefile for hisilicon drm drivers.
# Please keep this list sorted alphabetically
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
new file mode 100644
index 0000000..a9af90d
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -0,0 +1,7 @@
+config DRM_HISI_HIBMC
+ tristate "DRM Support for Hisilicon Hibmc"
+ depends on DRM && PCI
+
+ help
+ Choose this option if you have a Hisilicon Hibmc soc chipset.
+ If M is selected the module will be called hibmc-drm.
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
new file mode 100644
index 0000000..97cf4a0
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -0,0 +1,5 @@
+ccflags-y := -Iinclude/drm
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+
+obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o
+#obj-y += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
new file mode 100644
index 0000000..4669d42
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -0,0 +1,269 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/console.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+static const struct file_operations hibmc_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .poll = drm_poll,
+ .read = drm_read,
+ .llseek = no_llseek,
+};
+
+static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+ return 0;
+}
+
+static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+}
+
+static struct drm_driver hibmc_driver = {
+ .fops = &hibmc_fops,
+ .name = "hibmc",
+ .date = "20160828",
+ .desc = "hibmc drm driver",
+ .major = 1,
+ .minor = 0,
+ .get_vblank_counter = drm_vblank_no_hw_counter,
+ .enable_vblank = hibmc_enable_vblank,
+ .disable_vblank = hibmc_disable_vblank,
+};
+
+static int hibmc_pm_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int hibmc_pm_resume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops hibmc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
+ hibmc_pm_resume)
+};
+
+static int hibmc_hw_config(struct hibmc_drm_device *hidev)
+{
+ unsigned int reg;
+
+ /* On hardware reset, power mode 0 is default. */
+ hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+ /* Enable display power gate & LOCALMEM power gate*/
+ reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+ reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+ reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+ reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+ reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+
+ hibmc_set_current_gate(hidev, reg);
+
+ /* Reset the memory controller. If the memory controller
+ * is not reset in chip,the system might hang when sw accesses
+ * the memory.The memory should be resetted after
+ * changing the MXCLK.
+ */
+ reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
+ reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+ reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
+ writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
+
+ reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+ reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
+
+ writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
+
+ /* We can add more initialization as needed. */
+
+ return 0;
+}
+
+static int hibmc_hw_map(struct hibmc_drm_device *hidev)
+{
+ struct drm_device *dev = hidev->dev;
+ struct pci_dev *pdev = dev->pdev;
+ resource_size_t addr, size, ioaddr, iosize;
+
+ ioaddr = pci_resource_start(pdev, 1);
+ iosize = MB(2);
+
+ hidev->mmio = ioremap_nocache(ioaddr, iosize);
+
+ if (!hidev->mmio) {
+ DRM_ERROR("Cannot map mmio region\n");
+ return -ENOMEM;
+ }
+
+ addr = pci_resource_start(pdev, 0);
+ size = MB(32);
+
+ hidev->fb_map = ioremap(addr, size);
+ if (!hidev->fb_map) {
+ DRM_ERROR("Cannot map framebuffer\n");
+ return -ENOMEM;
+ }
+ hidev->fb_base = addr;
+ hidev->fb_size = size;
+
+ return 0;
+}
+
+static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
+{
+ if (hidev->mmio)
+ iounmap(hidev->mmio);
+ if (hidev->fb_map)
+ iounmap(hidev->fb_map);
+}
+
+static int hibmc_hw_init(struct hibmc_drm_device *hidev)
+{
+ int ret;
+
+ ret = hibmc_hw_map(hidev);
+ if (ret)
+ return ret;
+
+ hibmc_hw_config(hidev);
+
+ return 0;
+}
+
+static int hibmc_unload(struct drm_device *dev)
+{
+ struct hibmc_drm_device *hidev = dev->dev_private;
+
+ hibmc_hw_fini(hidev);
+ dev->dev_private = NULL;
+ return 0;
+}
+
+static int hibmc_load(struct drm_device *dev, unsigned long flags)
+{
+ struct hibmc_drm_device *hidev;
+ int ret;
+
+ hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
+ if (!hidev)
+ return -ENOMEM;
+ dev->dev_private = hidev;
+ hidev->dev = dev;
+
+ ret = hibmc_hw_init(hidev);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ hibmc_unload(dev);
+ DRM_ERROR("failed to initialize drm driver.\n");
+ return ret;
+}
+
+static int hibmc_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct drm_device *dev;
+ int ret;
+
+ dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->pdev = pdev;
+ pci_set_drvdata(pdev, dev);
+
+ ret = pci_enable_device(pdev);
+ if (ret)
+ goto err_free;
+
+ ret = hibmc_load(dev, 0);
+ if (ret)
+ goto err_disable;
+
+ ret = drm_dev_register(dev, 0);
+ if (ret)
+ goto err_unload;
+
+ return 0;
+
+err_unload:
+ hibmc_unload(dev);
+err_disable:
+ pci_disable_device(pdev);
+err_free:
+ drm_dev_unref(dev);
+
+ return ret;
+}
+
+static void hibmc_pci_remove(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_dev_unregister(dev);
+ hibmc_unload(dev);
+ drm_dev_unref(dev);
+}
+
+static struct pci_device_id hibmc_pci_table[] = {
+ {0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+static struct pci_driver hibmc_pci_driver = {
+ .name = "hibmc-drm",
+ .id_table = hibmc_pci_table,
+ .probe = hibmc_pci_probe,
+ .remove = hibmc_pci_remove,
+ .driver.pm = &hibmc_pm_ops,
+};
+
+static int __init hibmc_init(void)
+{
+ return pci_register_driver(&hibmc_pci_driver);
+}
+
+static void __exit hibmc_exit(void)
+{
+ return pci_unregister_driver(&hibmc_pci_driver);
+}
+
+module_init(hibmc_init);
+module_exit(hibmc_exit);
+
+MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
+MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
+MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
new file mode 100644
index 0000000..0037341
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -0,0 +1,35 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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.
+ *
+ */
+
+#ifndef HIBMC_DRM_DRV_H
+#define HIBMC_DRM_DRV_H
+
+#include <drm/drmP.h>
+
+struct hibmc_drm_device {
+ /* hw */
+ void __iomem *mmio;
+ void __iomem *fb_map;
+ unsigned long fb_base;
+ unsigned long fb_size;
+
+ /* drm */
+ struct drm_device *dev;
+};
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
new file mode 100644
index 0000000..1036542
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
@@ -0,0 +1,85 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+/*
+ * It can operate in one of three modes: 0, 1 or Sleep.
+ */
+void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
+ unsigned int power_mode)
+{
+ unsigned int control_value = 0;
+ void __iomem *mmio = hidev->mmio;
+
+ if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
+ return;
+
+ control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
+ control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
+
+ control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
+ HIBMC_PW_MODE_CTL_MODE_MASK;
+
+ /* Set up other fields in Power Control Register */
+ if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
+ control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+ control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
+ HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+ } else {
+ control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+ control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
+ HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+ }
+ /* Program new power mode. */
+ writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
+}
+
+static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
+{
+ void __iomem *mmio = hidev->mmio;
+
+ return (readl(mmio + HIBMC_POWER_MODE_CTRL) &
+ HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
+}
+
+void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
+{
+ unsigned int gate_reg;
+ unsigned int mode;
+ void __iomem *mmio = hidev->mmio;
+
+ /* Get current power mode. */
+ mode = hibmc_get_power_mode(hidev);
+
+ switch (mode) {
+ case HIBMC_PW_MODE_CTL_MODE_MODE0:
+ gate_reg = HIBMC_MODE0_GATE;
+ break;
+
+ case HIBMC_PW_MODE_CTL_MODE_MODE1:
+ gate_reg = HIBMC_MODE1_GATE;
+ break;
+
+ default:
+ gate_reg = HIBMC_MODE0_GATE;
+ break;
+ }
+ writel(gate, mmio + gate_reg);
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
new file mode 100644
index 0000000..e20e1aa
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
@@ -0,0 +1,28 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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.
+ *
+ */
+
+#ifndef HIBMC_DRM_POWER_H
+#define HIBMC_DRM_POWER_H
+
+#include "hibmc_drm_drv.h"
+
+void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
+ unsigned int power_mode);
+void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
+ unsigned int gate);
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
new file mode 100644
index 0000000..9c804ca
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
@@ -0,0 +1,212 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ * Rongrong Zou <zourongrong@huawei.com>
+ * Rongrong Zou <zourongrong@gmail.com>
+ * Jianhua Li <lijianhua@huawei.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.
+ *
+ */
+
+#ifndef HIBMC_DRM_HW_H
+#define HIBMC_DRM_HW_H
+
+#define OFF 0
+#define ON 1
+#define DISABLE 0
+#define ENABLE 1
+
+/* register definition */
+#define HIBMC_MISC_CTRL 0x4
+
+#define HIBMC_MSCCTL_LOCALMEM_RESET(x) ((x) << 6)
+#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK 0x40
+
+#define RESET 0
+#define NORMAL 1
+
+#define HIBMC_CURRENT_GATE 0x000040
+#define HIBMC_CURR_GATE_DISPLAY(x) ((x) << 2)
+#define HIBMC_CURR_GATE_DISPLAY_MASK 0x4
+
+#define HIBMC_CURR_GATE_LOCALMEM(x) ((x) << 1)
+#define HIBMC_CURR_GATE_LOCALMEM_MASK 0x2
+
+#define HIBMC_MODE0_GATE 0x000044
+#define HIBMC_MODE1_GATE 0x000048
+#define HIBMC_POWER_MODE_CTRL 0x00004C
+
+#define HIBMC_PW_MODE_CTL_OSC_INPUT(x) ((x) << 3)
+#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK 0x8
+
+#define HIBMC_PW_MODE_CTL_MODE(x) ((x) << 0)
+#define HIBMC_PW_MODE_CTL_MODE_MASK 0x03
+#define HIBMC_PW_MODE_CTL_MODE_SHIFT 0
+
+#define HIBMC_PW_MODE_CTL_MODE_MODE0 0
+#define HIBMC_PW_MODE_CTL_MODE_MODE1 1
+#define HIBMC_PW_MODE_CTL_MODE_SLEEP 2
+
+#define HIBMC_PANEL_PLL_CTRL 0x00005C
+#define HIBMC_CRT_PLL_CTRL 0x000060
+
+#define HIBMC_PLL_CTRL_BYPASS(x) ((x) << 18)
+#define HIBMC_PLL_CTRL_BYPASS_MASK 0x40000
+
+#define HIBMC_PLL_CTRL_POWER(x) ((x) << 17)
+#define HIBMC_PLL_CTRL_POWER_MASK 0x20000
+
+#define HIBMC_PLL_CTRL_INPUT(x) ((x) << 16)
+#define HIBMC_PLL_CTRL_INPUT_MASK 0x10000
+
+#define OSC 0
+#define TESTCLK 1
+
+#define HIBMC_PLL_CTRL_POD(x) ((x) << 14)
+#define HIBMC_PLL_CTRL_POD_MASK 0xC000
+
+#define HIBMC_PLL_CTRL_OD(x) ((x) << 12)
+#define HIBMC_PLL_CTRL_OD_MASK 0x3000
+
+#define HIBMC_PLL_CTRL_N(x) ((x) << 8)
+#define HIBMC_PLL_CTRL_N_MASK 0xF00
+
+#define HIBMC_PLL_CTRL_M(x) ((x) << 0)
+#define HIBMC_PLL_CTRL_M_MASK 0xFF
+
+#define HIBMC_CRT_DISP_CTL 0x80200
+
+#define HIBMC_CRT_DISP_CTL_CRTSELECT(x) ((x) << 25)
+#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK 0x2000000
+
+#define CRTSELECT_VGA 0
+#define CRTSELECT_CRT 1
+
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x) ((x) << 14)
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK 0x4000
+
+#define PHASE_ACTIVE_HIGH 0
+#define PHASE_ACTIVE_LOW 1
+
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x) ((x) << 13)
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK 0x2000
+
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x) ((x) << 12)
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK 0x1000
+
+#define HIBMC_CRT_DISP_CTL_TIMING(x) ((x) << 8)
+#define HIBMC_CRT_DISP_CTL_TIMING_MASK 0x100
+
+#define HIBMC_CRT_DISP_CTL_PLANE(x) ((x) << 2)
+#define HIBMC_CRT_DISP_CTL_PLANE_MASK 4
+
+#define HIBMC_CRT_DISP_CTL_FORMAT(x) ((x) << 0)
+#define HIBMC_CRT_DISP_CTL_FORMAT_MASK 0x03
+
+#define HIBMC_CRT_FB_ADDRESS 0x080204
+
+#define HIBMC_CRT_FB_WIDTH 0x080208
+#define HIBMC_CRT_FB_WIDTH_WIDTH(x) ((x) << 16)
+#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK 0x3FFF0000
+#define HIBMC_CRT_FB_WIDTH_OFFS(x) ((x) << 0)
+#define HIBMC_CRT_FB_WIDTH_OFFS_MASK 0x3FFF
+
+#define HIBMC_CRT_HORZ_TOTAL 0x08020C
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x) ((x) << 16)
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK 0xFFF0000
+
+#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x) ((x) << 0)
+#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK 0xFFF
+
+#define HIBMC_CRT_HORZ_SYNC 0x080210
+#define HIBMC_CRT_HORZ_SYNC_WIDTH(x) ((x) << 16)
+#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK 0xFF0000
+
+#define HIBMC_CRT_HORZ_SYNC_START(x) ((x) << 0)
+#define HIBMC_CRT_HORZ_SYNC_START_MASK 0xFFF
+
+#define HIBMC_CRT_VERT_TOTAL 0x080214
+#define HIBMC_CRT_VERT_TOTAL_TOTAL(x) ((x) << 16)
+#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK 0x7FFF0000
+
+#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x) ((x) << 0)
+#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK 0x7FF
+
+#define HIBMC_CRT_VERT_SYNC 0x080218
+#define HIBMC_CRT_VERT_SYNC_HEIGHT(x) ((x) << 16)
+#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK 0x3F0000
+
+#define HIBMC_CRT_VERT_SYNC_START(x) ((x) << 0)
+#define HIBMC_CRT_VERT_SYNC_START_MASK 0x7FF
+
+/* Auto Centering */
+#define HIBMC_CRT_AUTO_CENTERING_TL 0x080280
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x) ((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK 0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x) ((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK 0x7FF
+
+#define HIBMC_CRT_AUTO_CENTERING_BR 0x080284
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x) ((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK 0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x) ((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK 0x7FF
+
+/* register to control panel output */
+#define DISPLAY_CONTROL_HISILE 0x80288
+
+#define HIBMC_RAW_INTERRUPT 0x80290
+#define HIBMC_RAW_INTERRUPT_VBLANK(x) ((x) << 2)
+#define HIBMC_RAW_INTERRUPT_VBLANK_MASK 0x4
+
+#define HIBMC_RAW_INTERRUPT_EN 0x80298
+#define HIBMC_RAW_INTERRUPT_EN_VBLANK(x) ((x) << 2)
+#define HIBMC_RAW_INTERRUPT_EN_VBLANK_MASK 0x4
+
+/* register and values for PLL control */
+#define CRT_PLL1_HS 0x802a8
+#define CRT_PLL1_HS_25MHZ 0x23d40f02
+#define CRT_PLL1_HS_40MHZ 0x23940801
+#define CRT_PLL1_HS_65MHZ 0x23940d01
+#define CRT_PLL1_HS_78MHZ 0x23540F82
+#define CRT_PLL1_HS_74MHZ 0x23941dc2
+#define CRT_PLL1_HS_80MHZ 0x23941001
+#define CRT_PLL1_HS_80MHZ_1152 0x23540fc2
+#define CRT_PLL1_HS_108MHZ 0x23b41b01
+#define CRT_PLL1_HS_162MHZ 0x23480681
+#define CRT_PLL1_HS_148MHZ 0x23541dc2
+#define CRT_PLL1_HS_193MHZ 0x234807c1
+
+#define CRT_PLL2_HS 0x802ac
+#define CRT_PLL2_HS_25MHZ 0x206B851E
+#define CRT_PLL2_HS_40MHZ 0x30000000
+#define CRT_PLL2_HS_65MHZ 0x40000000
+#define CRT_PLL2_HS_78MHZ 0x50E147AE
+#define CRT_PLL2_HS_74MHZ 0x602B6AE7
+#define CRT_PLL2_HS_80MHZ 0x70000000
+#define CRT_PLL2_HS_108MHZ 0x80000000
+#define CRT_PLL2_HS_162MHZ 0xA0000000
+#define CRT_PLL2_HS_148MHZ 0xB0CCCCCD
+#define CRT_PLL2_HS_193MHZ 0xC0872B02
+
+/* Global macros */
+#define RGB(r, g, b) \
+( \
+ (unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
+)
+
+#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
+
+#define MB(x) ((x) << 20)
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v6 0/9] Add DRM driver for Hisilicon Hibmc
From: Rongrong Zou @ 2016-10-28 7:27 UTC (permalink / raw)
To: linux-arm-kernel
This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
BMC SoC with a display controller intergrated, usually it is used on
server for Out-of-band management purpose. In this patch set, we just
support basic function for Hibmc display subsystem. Hibmc display
subsystem is connected to host CPU by PCIe as blow:
+----------+ +----------+
| | PCIe | Hibmc |
|host CPU( |<----->| display |
|arm64,x86)| |subsystem |
+----------+ +----------+
Hardware Detail for Hibmc display subsystem
-----------
The display subsystem of Hibmc is show as bellow:
+----+ +----+ +----+ +--------+
| | | | | | | |
| FB |----->| DE |----->|VDAC|---->|external|
| | | | | | | VGA |
+----+ +----+ +----+ +--------+
-DE(Display Engine) is the display controller.
-VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
stream from DE to VGA analog signals.
Change History
------------
Changes in v6:
-remove the embedded framebuffer and use a pointer of hibmc_framebuffer
instead.
-remove the deprecated drm_framebuffer_unregister_private(),
drm_framebuffer_unreference() will be called in hibmc_fbdev_destroy().
-uninstall irq in hibmc_unload().
Changes in v5:
-rebase on v4.9-rc2.
-replace drm_fb_helper_set_suspend with drm_fb_helper_set_suspend_unlocked.
and remove redundant console_lock and console_unlock.
Changes in v4:
-remove unused include files, and include header file when it is needed.
-remove unused FLAG in Kconfig: DRM_GEM_CMA_HELPER/DRM_KMS_CMA_HELPER.
-remove drm_helper_disable_unused_functions, since we use DRIVER_ATOMIC.
Changes in v3:
-enable KMS, in v2, only fbdev is enabled.
-management video memory with ttm.
-add vblank interrupt.
-remove drm_connector_register_all() and drm_connector_unregister_all().
-I have a basic test with igt.
Changes in v2:
-Remove self-defined macros for bit operations.
-Remove unused register.
-Replace those deprecated functions with new version of them.
-use drm_connector_register_all() to register connector after
drm_dev_register().
The patch v2 is at
https://lists.freedesktop.org/archives/dri-devel/2016-May/108661.html
Rongrong Zou (9):
drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
drm/hisilicon/hibmc: Add video memory management
drm/hisilicon/hibmc: Add support for frame buffer
drm/hisilicon/hibmc: Add plane for DE
drm/hisilicon/hibmc: Add crtc for DE
drm/hisilicon/hibmc: Add encoder for VDAC
drm/hisilicon/hibmc: Add connector for VDAC
drm/hisilicon/hibmc: Add vblank interruput
MAINTAINERS: Update HISILICON DRM entries
MAINTAINERS | 1 +
drivers/gpu/drm/hisilicon/Kconfig | 1 +
drivers/gpu/drm/hisilicon/Makefile | 1 +
drivers/gpu/drm/hisilicon/hibmc/Kconfig | 9 +
drivers/gpu/drm/hisilicon/hibmc/Makefile | 5 +
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 488 +++++++++++++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h | 29 ++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 419 ++++++++++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 117 +++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 255 ++++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c | 85 ++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h | 28 ++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h | 212 ++++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 165 +++++++
drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 562 ++++++++++++++++++++++
15 files changed, 2377 insertions(+)
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
--
1.9.1
^ permalink raw reply
* [PATCH v2 2/2] arm64: dts: hi6220: add resets property into dwmmc nodes
From: Leo Yan @ 2016-10-28 7:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKfTPtAXdkKcfpHmUmQNwuJxO0PORcCf49noST_CCkZPigPwgw@mail.gmail.com>
On Fri, Oct 28, 2016 at 08:43:51AM +0200, Vincent Guittot wrote:
[...]
> > running with? Also do you have any details about the card in case its
> > card specific?
>
> The sdcard is quite common: sandisk ultra 16GB
> and my rootfs is on the sdcard
I'm using rootfs in emmc also have same failure.
> > Guodong: Is there any bootloader dependency on that change?
>
> FYI, I use firmwares available in AOSP
I tried latest firmware [1], still cannot boot up until revert the
patch "arm64: dts: hi6220: add resets property into dwmmc nodes".
[1] http://builds.96boards.org/snapshots/hikey/linaro/uefi-openplatformpkg/latest/
Thanks,
Leo Yan
^ permalink raw reply
* [PATCHv4 00/15] clk: ti: add support for hwmod clocks
From: Tero Kristo @ 2016-10-28 7:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028005341.GR26139@codeaurora.org>
On 28/10/16 03:53, Stephen Boyd wrote:
> On 10/18, Tero Kristo wrote:
>> Hi,
>>
>> As a recap, this series is part of the ongoing work to get rid of the
>> hwmod database under mach-omap2 folder. This series converts the
>> existing clock related functionality to a new clock type, which will
>> allow removing all the .clkctrl related items from hwmod database.
>> This series adds sample solution for OMAP4 only, rest of the SoCs can
>> be converted automatically once the approach is acceptable.
>>
>> v4 has the following high level changes compared to v3:
>> - Clock data is now statically built-in to the driver
>> - Adds clockdomain provider support, which can be used to fetch
>> clocks based on clockdomain relation. Only clockdomains need to be
>> registered within DT.
>> - Added some automatic clock alias generation support to the TI clock
>> drivers, if this is not acceptable, I can change this to add all the
>> aliases under the individual drivers/clk/ti/clk-xyz.c files
>
> Is there a plan to get rid of the aliases entirely? Or we can't
> do that because DT is not fully supported on these platforms? I'm
> mostly wondering how long that sort of code is going to stick
> around and if it's better to fully compartmentalize it to the
> SoCs that are affected or if it should be a core feature of TI
> driver.
Eventually that should happen. However, we have plenty of legacy code
still in place which depend on clk_get functionality within kernel. The
major contributing factor is the hwmod codebase, for which we have plans to:
- get this clock driver merged
- implement a new interconnect driver for OMAP family SoCs
- interconnect driver will use DT handles for fetching clocks, rather
than clock aliases
- reset handling will be implemented as part of the interconnect driver
somehow (no prototype / clear plans for that as of yet)
- all the hwmod stuff can be dropped
The clock alias handling is still needed as a transition phase until all
the above is done, then we can start dropping them. Basically anything
that is using omap_hwmod depends on the clock aliases right now.
>
>> - As a sample, only omap4 clock data is available with this set
>>
>> After this series, the clock data can be dropped from the hwmod database
>> for OMAP4, I have working patches for this for anybody interested. Also,
>> the DT files require some modifications to add proper support for
>> clockdomain providers, and drop some unnecessary clock nodes.
>
> Can this be shared as a git tree on the web? Hopefully I can see
> the resulting DTS and understand what's going on better.
Sure, here is a test branch I've been using, it has some extra hacks on
top for debugging purposes, but the DTS changes are visible also.
https://github.com/t-kristo/linux-pm/tree/4.9-rc1-hwmod-clks-w-data
>
>>
>> Boot + simple PM test seems to be working on OMAP4 with this set, and
>> boot test with other boards I have access to don't seem to cause any
>> issues. Applies on top of 4.9-rc1.
>>
>
> Awesome!
>
^ permalink raw reply
* [v13, 5/8] soc: fsl: add GUTS driver for QorIQ platforms
From: Y.B. Lu @ 2016-10-28 7:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477629956.6812.15.camel@buserror.net>
> -----Original Message-----
> From: Y.B. Lu
> Sent: Friday, October 28, 2016 2:06 PM
> To: Y.B. Lu; 'Scott Wood'; 'linux-mmc at vger.kernel.org';
> 'ulf.hansson at linaro.org'; 'Arnd Bergmann'
> Cc: 'linuxppc-dev at lists.ozlabs.org'; 'devicetree at vger.kernel.org';
> 'linux-arm-kernel at lists.infradead.org'; 'linux-kernel at vger.kernel.org';
> 'linux-clk at vger.kernel.org'; 'linux-i2c at vger.kernel.org';
> 'iommu at lists.linux-foundation.org'; 'netdev at vger.kernel.org'; 'Greg
> Kroah-Hartman'; 'Mark Rutland'; 'Rob Herring'; 'Russell King'; 'Jochen
> Friedrich'; 'Joerg Roedel'; 'Claudiu Manoil'; 'Bhupesh Sharma'; Qiang
> Zhao; 'Kumar Gala'; 'Santosh Shilimkar'; Leo Li; X.B. Xie; M.H. Lian
> Subject: RE: [v13, 5/8] soc: fsl: add GUTS driver for QorIQ platforms
>
> > -----Original Message-----
> > From: Y.B. Lu
> > Sent: Friday, October 28, 2016 2:00 PM
> > To: 'Scott Wood'; linux-mmc at vger.kernel.org; ulf.hansson at linaro.org;
> > Arnd Bergmann
> > Cc: linuxppc-dev at lists.ozlabs.org; devicetree at vger.kernel.org;
> > linux-arm- kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> > linux- clk at vger.kernel.org; linux-i2c at vger.kernel.org;
> > iommu at lists.linux- foundation.org; netdev at vger.kernel.org; Greg
> > Kroah-Hartman; Mark Rutland; Rob Herring; Russell King; Jochen
> > Friedrich; Joerg Roedel; Claudiu Manoil; Bhupesh Sharma; Qiang Zhao;
> Kumar Gala; Santosh Shilimkar; Leo Li; X.B.
> > Xie; M.H. Lian
> > Subject: RE: [v13, 5/8] soc: fsl: add GUTS driver for QorIQ platforms
> >
> >
> >
> > > -----Original Message-----
> > > From: linux-mmc-owner at vger.kernel.org [mailto:linux-mmc-
> > > owner at vger.kernel.org] On Behalf Of Scott Wood
> > > Sent: Friday, October 28, 2016 12:46 PM
> > > To: Y.B. Lu; linux-mmc at vger.kernel.org; ulf.hansson at linaro.org; Arnd
> > > Bergmann
> > > Cc: linuxppc-dev at lists.ozlabs.org; devicetree at vger.kernel.org;
> > > linux-arm- kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> > > linux- clk at vger.kernel.org; linux-i2c at vger.kernel.org;
> > > iommu at lists.linux- foundation.org; netdev at vger.kernel.org; Greg
> > > Kroah-Hartman; Mark Rutland; Rob Herring; Russell King; Jochen
> > > Friedrich; Joerg Roedel; Claudiu Manoil; Bhupesh Sharma; Qiang Zhao;
> > Kumar Gala; Santosh Shilimkar; Leo Li; X.B.
> > > Xie; M.H. Lian
> > > Subject: Re: [v13, 5/8] soc: fsl: add GUTS driver for QorIQ
> > > platforms
> > >
> > > On Fri, 2016-10-28 at 11:32 +0800, Yangbo Lu wrote:
> > > > + guts->regs = of_iomap(np, 0);
> > > > + if (!guts->regs)
> > > > + return -ENOMEM;
> > > > +
> > > > + /* Register soc device */
> > > > + machine = of_flat_dt_get_machine_name();
> > > > + if (machine)
> > > > + soc_dev_attr.machine = devm_kstrdup(dev, machine,
> > > > GFP_KERNEL);
> > > > +
> > > > + svr = fsl_guts_get_svr();
> > > > + soc_die = fsl_soc_die_match(svr, fsl_soc_die);
> > > > + if (soc_die) {
> > > > + soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL,
> > > > + ?????"QorIQ %s", soc_die-
> > > > >die);
> > > > + } else {
> > > > + soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL,
> > > > "QorIQ");
> > > > + }
> > > > + soc_dev_attr.soc_id = devm_kasprintf(dev, GFP_KERNEL,
> > > > + ?????"svr:0x%08x", svr);
> > > > + soc_dev_attr.revision = devm_kasprintf(dev, GFP_KERNEL,
> "%d.%d",
> > > > + ???????SVR_MAJ(svr), SVR_MIN(svr));
> > > > +
> > > > + soc_dev = soc_device_register(&soc_dev_attr);
> > > > + if (IS_ERR(soc_dev))
> > > > + return PTR_ERR(soc_dev);
> > >
> > > ioremap leaks on this error path. ?Use devm_ioremap_resource().
> > >
> >
> > [Lu Yangbo-B47093] Ok. I have fixed it in v14. Thanks :)
>
> [Lu Yangbo-B47093] Sorry, used the wrong error code... Will resent it
[Lu Yangbo-B47093] The v15 had been sent. And dropped patch 'dt: bindings: update Freescale DCFG compatible',
since that work has been done by below patch on ShawnGuo's linux tree.
'dt-bindings: fsl: add LS1043A/LS1046A/LS2080A compatible for SCFG and DCFG'
https://git.kernel.org/cgit/linux/kernel/git/shawnguo/linux.git/commit/?h=imx/dt64&id=981034a2bfcaff5c95dafde24d7abfe7f9025c19
Thanks.
>
> >
> > > -Scott
> > >
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-mmc"
> > > in the body of a message to majordomo at vger.kernel.org More majordomo
> > > info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 3/3] ARM: dts: sun8i: Add dts file for NanoPi M1 SBC
From: Milo Kim @ 2016-10-28 6:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028065903.23298-1-woogyom.kim@gmail.com>
NanoPi M1 is the Allwinner H3 based board.
This patch enables UART for debug console, LEDs, GPIO key switch, 3 USB
host ports, a micro SD slot and related power and pin controls by using
NanoPi common dtsi file.
Cc: James Pettigrew <james@innovum.com.au>
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts | 64 ++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
new file mode 100644
index 0000000..ec63d10
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 Milo Kim <woogyom.kim@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sun8i-h3-nanopi.dtsi"
+
+/ {
+ model = "FriendlyArm NanoPi M1";
+ compatible = "friendlyarm,nanopi-m1", "allwinner,sun8i-h3";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 2/3] ARM: dts: sun8i: Use the common file in NanoPi NEO SBC
From: Milo Kim @ 2016-10-28 6:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028065903.23298-1-woogyom.kim@gmail.com>
NanoPi common dtsi supports all components of NEO SBC, so just include it.
Cc: James Pettigrew <james@innovum.com.au>
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 79 +------------------------------
1 file changed, 1 insertion(+), 78 deletions(-)
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
index 3d64caf..8d2cc6e 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
@@ -40,86 +40,9 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-/dts-v1/;
-#include "sun8i-h3.dtsi"
-#include "sunxi-common-regulators.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include "sun8i-h3-nanopi.dtsi"
/ {
model = "FriendlyARM NanoPi NEO";
compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
-
- aliases {
- serial0 = &uart0;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
-
- pwr {
- label = "nanopi:green:pwr";
- gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
- default-state = "on";
- };
-
- status {
- label = "nanopi:blue:status";
- gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */
- };
- };
-};
-
-&ehci3 {
- status = "okay";
-};
-
-&mmc0 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
- vmmc-supply = <®_vcc3v3>;
- bus-width = <4>;
- cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
- cd-inverted;
- status = "okay";
-};
-
-&ohci3 {
- status = "okay";
-};
-
-&pio {
- leds_opc: led-pins {
- allwinner,pins = "PA10";
- allwinner,function = "gpio_out";
- allwinner,drive = <SUN4I_PINCTRL_10_MA>;
- allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
- };
-};
-
-&r_pio {
- leds_r_opc: led-pins {
- allwinner,pins = "PL10";
- allwinner,function = "gpio_out";
- allwinner,drive = <SUN4I_PINCTRL_10_MA>;
- allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
- };
-};
-
-&uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_pins_a>;
- status = "okay";
-};
-
-&usbphy {
- /* USB VBUS is always on */
- status = "okay";
};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 1/3] ARM: dts: sun8i: Add common dtsi file for NanoPi SBCs
From: Milo Kim @ 2016-10-28 6:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028065903.23298-1-woogyom.kim@gmail.com>
This patch provides a common file for NanoPi M1 and Neo SBC.
Those have common features below.
* UART0
* 2 LEDs
* USB host (EHCI3, OHCI3) and PHY
* MicroSD
* GPIO key switch
Cc: James Pettigrew <james@innovum.com.au>
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
arch/arm/boot/dts/sun8i-h3-nanopi.dtsi | 144 +++++++++++++++++++++++++++++++++
1 file changed, 144 insertions(+)
create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi b/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
new file mode 100644
index 0000000..8038aa2
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 James Pettigrew <james@innovum.com.au>
+ * Copyright (C) 2016 Milo Kim <woogyom.kim@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&leds_npi>, <&leds_r_npi>;
+
+ status {
+ label = "nanopi:blue:status";
+ gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ pwr {
+ label = "nanopi:green:pwr";
+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+ };
+
+ r_gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "k1";
+ pinctrl-names = "default";
+ pinctrl-0 = <&sw_r_npi>;
+
+ k1 at 0 {
+ label = "k1";
+ linux,code = <KEY_POWER>;
+ gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&mmc0 {
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+ status = "okay";
+ vmmc-supply = <®_vcc3v3>;
+};
+
+&ohci3 {
+ status = "okay";
+};
+
+&pio {
+ leds_npi: led_pins at 0 {
+ allwinner,pins = "PA10";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+};
+
+&r_pio {
+ leds_r_npi: led_pins at 0 {
+ allwinner,pins = "PL10";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
+ sw_r_npi: key_pins at 0 {
+ allwinner,pins = "PL3";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+&usbphy {
+ status = "okay";
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 0/3] ARM: dts: sun8i: Support NanoPi SBCs
From: Milo Kim @ 2016-10-28 6:59 UTC (permalink / raw)
To: linux-arm-kernel
NanoPi M1 and NEO have common features, so duplicate properties can be
moved into new dtsi file.
v2:
Add James's copyrights in NanoPi common dtsi file
Milo Kim (3):
ARM: dts: sun8i: Add common dtsi file for NanoPi SBCs
ARM: dts: sun8i: Use the common file in NanoPi NEO SBC
ARM: dts: sun8i: Add dts file for NanoPi M1 SBC
arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts | 64 +++++++++++++
arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 79 +---------------
arch/arm/boot/dts/sun8i-h3-nanopi.dtsi | 144 ++++++++++++++++++++++++++++++
3 files changed, 209 insertions(+), 78 deletions(-)
create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
create mode 100644 arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
--
2.9.3
^ permalink raw reply
* [PATCH v2 4/4] spi: sun6i: Support Allwinner H3 SPI controller
From: Milo Kim @ 2016-10-28 6:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028065412.23008-1-woogyom.kim@gmail.com>
H3 has two SPI controllers. The size of the buffer is 64 * 8.
(8 bit transfer by 64 entry FIFO)
A31 has four controllers. The size of the buffer is 128 * 8.
(8 bit transfer by 128 entry FIFO)
Register maps are sharable, so sun6i SPI driver is reusable with
device configuration.
Use the variable, 'fifo_depth' instead of fixed value to support both SPI
controllers.
Cc: Mark Brown <broonie@kernel.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
drivers/spi/spi-sun6i.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 9918a57..e311483 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
@@ -24,6 +25,7 @@
#include <linux/spi/spi.h>
#define SUN6I_FIFO_DEPTH 128
+#define SUN8I_FIFO_DEPTH 64
#define SUN6I_GBL_CTL_REG 0x04
#define SUN6I_GBL_CTL_BUS_ENABLE BIT(0)
@@ -90,6 +92,7 @@ struct sun6i_spi {
const u8 *tx_buf;
u8 *rx_buf;
int len;
+ unsigned long fifo_depth;
};
static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
@@ -155,7 +158,9 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
{
- return SUN6I_FIFO_DEPTH - 1;
+ struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
+
+ return sspi->fifo_depth - 1;
}
static int sun6i_spi_transfer_one(struct spi_master *master,
@@ -170,7 +175,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
u32 reg;
/* We don't support transfer larger than the FIFO */
- if (tfr->len > SUN6I_FIFO_DEPTH)
+ if (tfr->len > sspi->fifo_depth)
return -EINVAL;
reinit_completion(&sspi->done);
@@ -265,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
SUN6I_BURST_CTL_CNT_STC(tx_len));
/* Fill the TX FIFO */
- sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+ sun6i_spi_fill_fifo(sspi, sspi->fifo_depth);
/* Enable the interrupts */
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
@@ -288,7 +293,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
goto out;
}
- sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+ sun6i_spi_drain_fifo(sspi, sspi->fifo_depth);
out:
sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
@@ -398,6 +403,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
}
sspi->master = master;
+ sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev);
+
master->max_speed_hz = 100 * 1000 * 1000;
master->min_speed_hz = 3 * 1000;
master->set_cs = sun6i_spi_set_cs;
@@ -470,7 +477,8 @@ static int sun6i_spi_remove(struct platform_device *pdev)
}
static const struct of_device_id sun6i_spi_match[] = {
- { .compatible = "allwinner,sun6i-a31-spi", },
+ { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH },
+ { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);
--
2.9.3
^ permalink raw reply related
* [PATCH v2 3/4] spi: sun6i: Add binding for Allwinner H3 SPI controller
From: Milo Kim @ 2016-10-28 6:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028065412.23008-1-woogyom.kim@gmail.com>
H3 SPI has same architecture as A31 except FIFO capacity.
To configure the buffer size separately, compatible property should be
different. Optional DMA specifiers and example are added.
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
.../devicetree/bindings/spi/spi-sun6i.txt | 25 ++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
index 21de73d..2ec99b8 100644
--- a/Documentation/devicetree/bindings/spi/spi-sun6i.txt
+++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
@@ -1,7 +1,7 @@
-Allwinner A31 SPI controller
+Allwinner A31/H3 SPI controller
Required properties:
-- compatible: Should be "allwinner,sun6i-a31-spi".
+- compatible: Should be "allwinner,sun6i-a31-spi" or "allwinner,sun8i-h3-spi".
- reg: Should contain register location and length.
- interrupts: Should contain interrupt.
- clocks: phandle to the clocks feeding the SPI controller. Two are
@@ -12,6 +12,11 @@ Required properties:
- resets: phandle to the reset controller asserting this device in
reset
+Optional properties:
+- dmas: DMA specifiers for rx and tx dma. See the DMA client binding,
+ Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request names should include "rx" and "tx" if present.
+
Example:
spi1: spi at 01c69000 {
@@ -22,3 +27,19 @@ spi1: spi at 01c69000 {
clock-names = "ahb", "mod";
resets = <&ahb1_rst 21>;
};
+
+spi0: spi at 01c68000 {
+ compatible = "allwinner,sun8i-h3-spi";
+ reg = <0x01c68000 0x1000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 23>, <&dma 23>;
+ dma-names = "rx", "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ resets = <&ccu RST_BUS_SPI0>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 2/4] ARM: dts: sun8i: Add SPI controller node in H3
From: Milo Kim @ 2016-10-28 6:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028065412.23008-1-woogyom.kim@gmail.com>
H3 SPI subsystem is almost same as A31 SPI except buffer size, so those
DT properties are reusable.
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 8a59d8d..c38b028 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -439,6 +439,38 @@
clocks = <&osc24M>;
};
+ spi0: spi at 01c68000 {
+ compatible = "allwinner,sun8i-h3-spi";
+ reg = <0x01c68000 0x1000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 23>, <&dma 23>;
+ dma-names = "rx", "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ resets = <&ccu RST_BUS_SPI0>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi at 01c69000 {
+ compatible = "allwinner,sun8i-h3-spi";
+ reg = <0x01c69000 0x1000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 24>, <&dma 24>;
+ dma-names = "rx", "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+ resets = <&ccu RST_BUS_SPI1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
wdt0: watchdog at 01c20ca0 {
compatible = "allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 1/4] ARM: dts: sun8i: Add SPI pinctrl node in H3
From: Milo Kim @ 2016-10-28 6:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028065412.23008-1-woogyom.kim@gmail.com>
H3 supports two SPI controllers. Four pins (MOSI, MISO, SCLK, SS) are
configured through the pinctrl subsystem.
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 75a8654..8a59d8d 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -381,6 +381,20 @@
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
+ spi0_pins: spi0 {
+ allwinner,pins = "PC0", "PC1", "PC2", "PC3";
+ allwinner,function = "spi0";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
+ spi1_pins: spi1 {
+ allwinner,pins = "PA15", "PA16", "PA14", "PA13";
+ allwinner,function = "spi1";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
uart0_pins_a: uart0 at 0 {
allwinner,pins = "PA4", "PA5";
allwinner,function = "uart0";
--
2.9.3
^ permalink raw reply related
* [PATCH v2 0/4] Support H3 SPI controller
From: Milo Kim @ 2016-10-28 6:54 UTC (permalink / raw)
To: linux-arm-kernel
Allwinner H3 SPI controller has same architecture as A31.
So most configuration is identical except one thing - FIFO capacity.
A31 H3
------------------------------------
Number of controllers 4 2
Number of FIFO depth 128 64
Transfer bits 8 8
Register maps are sharable, so sun6i SPI driver is reusable with
device configuration.
Tested on Nano Pi M1 and SPI slave device is TI LP8860.
v2:
Include DTS patches
Use of_device_get_match_data() helper to get device specific data
Fix build warning of 64bit CPU architecture
(warning: cast from pointer to integer of different size
[-Wpointer-to-int-cast])
Milo Kim (4):
ARM: dts: sun8i: Add SPI pinctrl node in H3
ARM: dts: sun8i: Add SPI controller node in H3
spi: sun6i: Add binding for Allwinner H3 SPI controller
spi: sun6i: Support Allwinner H3 SPI controller
.../devicetree/bindings/spi/spi-sun6i.txt | 25 +++++++++++-
arch/arm/boot/dts/sun8i-h3.dtsi | 46 ++++++++++++++++++++++
drivers/spi/spi-sun6i.c | 18 ++++++---
3 files changed, 82 insertions(+), 7 deletions(-)
--
2.9.3
^ permalink raw reply
* [v15, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
From: Yangbo Lu @ 2016-10-28 6:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477637418-38938-1-git-send-email-yangbo.lu@nxp.com>
The eSDHC of T4240-R1.0-R2.0 has incorrect vender version and spec version.
Acturally the right version numbers should be VVN=0x13 and SVN = 0x1.
This patch adds the GUTS driver support for eSDHC driver to match SoC.
And fix host version to avoid that incorrect version numbers break down
the ADMA data transfer.
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Scott Wood <oss@buserror.net>
---
Changes for v2:
- Got SVR through iomap instead of dts
Changes for v3:
- Managed GUTS through syscon instead of iomap in eSDHC driver
Changes for v4:
- Got SVR by GUTS driver instead of SYSCON
Changes for v5:
- Changed to get SVR through API fsl_guts_get_svr()
- Combined patch 4, patch 5 and patch 6 into one
Changes for v6:
- Added 'Acked-by: Ulf Hansson'
Changes for v7:
- None
Changes for v8:
- Added 'Acked-by: Scott Wood'
Changes for v9:
- None
Changes for v10:
- None
Changes for v11:
- Changed to use soc_device_match
Changes for v12:
- Matched soc through .family field instead of .soc_id
Changes for v13:
- None
Changes for v14:
- None
Changes for v15:
- None
---
drivers/mmc/host/Kconfig | 1 +
drivers/mmc/host/sdhci-of-esdhc.c | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5274f50..a1135a9 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -144,6 +144,7 @@ config MMC_SDHCI_OF_ESDHC
depends on MMC_SDHCI_PLTFM
depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
select MMC_SDHCI_IO_ACCESSORS
+ select FSL_GUTS
help
This selects the Freescale eSDHC controller support.
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index fb71c86..57bdb9e 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -18,6 +18,7 @@
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/sys_soc.h>
#include <linux/mmc/host.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
@@ -28,6 +29,7 @@
struct sdhci_esdhc {
u8 vendor_ver;
u8 spec_ver;
+ bool quirk_incorrect_hostver;
};
/**
@@ -73,6 +75,8 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host,
static u16 esdhc_readw_fixup(struct sdhci_host *host,
int spec_reg, u32 value)
{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
u16 ret;
int shift = (spec_reg & 0x2) * 8;
@@ -80,6 +84,12 @@ static u16 esdhc_readw_fixup(struct sdhci_host *host,
ret = value & 0xffff;
else
ret = (value >> shift) & 0xffff;
+ /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect
+ * vendor version and spec version information.
+ */
+ if ((spec_reg == SDHCI_HOST_VERSION) &&
+ (esdhc->quirk_incorrect_hostver))
+ ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
return ret;
}
@@ -558,6 +568,12 @@ static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = {
.ops = &sdhci_esdhc_le_ops,
};
+static struct soc_device_attribute soc_incorrect_hostver[] = {
+ { .family = "QorIQ T4240", .revision = "1.0", },
+ { .family = "QorIQ T4240", .revision = "2.0", },
+ { },
+};
+
static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host;
@@ -571,6 +587,10 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
SDHCI_VENDOR_VER_SHIFT;
esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;
+ if (soc_device_match(soc_incorrect_hostver))
+ esdhc->quirk_incorrect_hostver = true;
+ else
+ esdhc->quirk_incorrect_hostver = false;
}
static int sdhci_esdhc_probe(struct platform_device *pdev)
--
2.1.0.27.g96db324
^ 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