* [PATCH 4/5] regulator: Add support for TI TWL6032
From: kbuild test robot @ 2016-11-26 18:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161126181326.14951-5-Nicolae_Rosia@mentor.com>
Hi Nicolae,
[auto build test ERROR on omap/for-next]
[also build test ERROR on v4.9-rc6]
[cannot apply to next-20161125]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-twl-improvements-and-new-regulator-driver/20161127-022201
base: https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git for-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All error/warnings (new ones prefixed by >>):
In file included from drivers/regulator/twl6032-regulator.c:11:0:
>> drivers/regulator/twl6032-regulator.c:557:31: error: 'twl6032_regulator_driver_ids' undeclared here (not in a function)
MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
^
include/linux/module.h:213:21: note: in definition of macro 'MODULE_DEVICE_TABLE'
extern const typeof(name) __mod_##type##__##name##_device_table \
^~~~
>> include/linux/module.h:213:27: error: '__mod_platform__twl6032_regulator_driver_ids_device_table' aliased to undefined symbol 'twl6032_regulator_driver_ids'
extern const typeof(name) __mod_##type##__##name##_device_table \
^
>> drivers/regulator/twl6032-regulator.c:557:1: note: in expansion of macro 'MODULE_DEVICE_TABLE'
MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
^~~~~~~~~~~~~~~~~~~
vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-regulator.c
551
552 static const struct of_device_id twl6032_dt_match[] = {
553 { .compatible = "ti,twl6032-regulator" },
554 { /* last entry */ }
555 };
556
> 557 MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
558
559 static struct platform_driver twl6032_regulator_driver = {
560 .driver = {
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 56830 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161127/cdcde6ff/attachment-0001.gz>
^ permalink raw reply
* net: stmmac: Meson GXBB: attempting to execute userspace memory
From: Ben Dooks @ 2016-11-26 18:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <c8280798-453e-bd1d-bd4d-bf0956a169cc@gmx.de>
On 2016-11-26 07:53, Heinrich Schuchardt wrote:
> For Odroid C2 I have compiled kernel
> 4.9.0-rc6-next-20161124-00001-gbf7e142
> with one additional patch
> https://github.com/xypron/kernel-odroid-c2/blob/master/patch/0001-stmmac-RTL8211F-Meson-GXBB-TX-throughput-problems.patch
>
> I repeatedly see faults like the one below:
>
> [ 2557.400796] Unhandled fault: synchronous external abort (0x92000010)
> at 0x000040001e8ee4b0
> [ 2557.952413] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2557.962062] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2557.966980] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
> [ 2557.972846] PC is at 0x6a0d98
> [ 2557.975776] LR is at 0x6a0e54
> [ 2557.978709] pc : [<00000000006a0d98>] lr : [<00000000006a0e54>]
> pstate: 80000000
> [ 2557.986040] sp : 0000fffff3ee5f80
> [ 2557.989318] x29: 0000fffff3ee5f80 x28: 000040000b3f1240
> [ 2557.994578] x27: 00000000012a7000 x26: 000040000b3f1288
> [ 2557.999840] x25: 0000000000f58f88 x24: 000040000b3f1240
> [ 2558.005101] x23: 0000000000000000 x22: 0000000000000001
> [ 2558.010362] x21: 0000000000000001 x20: 000040000b3f1250
> [ 2558.015623] x19: 0000000000000054 x18: 0000000000000001
> [ 2558.020885] x17: 0000400008acaa10 x16: 0000000001285050
> [ 2558.026146] x15: 000040000ad96dc8 x14: 000000000000001f
> [ 2558.031407] x13: 000040000b3f1270 x12: 000040000b3f1258
> [ 2558.036668] x11: 0000000001347000 x10: 0000000000000661
> [ 2558.041930] x9 : 0000000000000005 x8 : 0000000000000003
> [ 2558.047191] x7 : 000040000b3f1240 x6 : 0000000020020033
> [ 2558.052452] x5 : 000040000b402020 x4 : 000040000b3e1aa0
> [ 2558.057713] x3 : 000000000000000c x2 : 0000000000000020
> [ 2558.062974] x1 : 0000000000f45000 x0 : 0000000000000065
> [ 2558.068235]
> [ 2558.069712] Internal error: Attempting to execute userspace memory:
> 8600000f [#7] PREEMPT SMP
> [ 2558.078155] Modules linked in: meson_rng rng_core meson_gxbb_wdt
> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
> stmmac_platform stmmac
> [ 2558.091267] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2558.100925] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2558.105841] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
> [ 2558.111706] PC is at 0x6a0e54
> [ 2558.114638] LR is at 0x6a0e54
> [ 2558.117571] pc : [<00000000006a0e54>] lr : [<00000000006a0e54>]
> pstate: 600003c5
> [ 2558.124902] sp : ffff80006dd9fec0
> [ 2558.128179] x29: 0000000000000000 x28: ffff80006ddb7080
> [ 2558.133441] x27: 00000000012a7000 x26: 000040000b3f1288
> [ 2558.138702] x25: 0000000000f58f88 x24: 000040000b3f1240
> [ 2558.143963] x23: 0000000080000000 x22: 00000000006a0d98
> [ 2558.149225] x21: ffffffffffffffff x20: 000080006e223000
> [ 2558.154486] x19: 0000000000000000 x18: 0000000000000010
> [ 2558.159747] x17: 0000400008acaa10 x16: 0000000001285050
> [ 2558.165008] x15: ffff000088e91f07 x14: 0000000000000006
> [ 2558.170270] x13: ffff000008e91f15 x12: 000000000000000f
> [ 2558.175531] x11: 0000000000000002 x10: 00000000000002ea
> [ 2558.180792] x9 : ffff80006dd9fb40 x8 : 0000000000010a8b
> [ 2558.186053] x7 : 0000000000000000 x6 : 000000000000020e
> [ 2558.191315] x5 : 00000000020f020e x4 : 0000000000000000
> [ 2558.196576] x3 : 0000000000000000 x2 : 000000000000020f
> [ 2558.201837] x1 : ffff80006ddb7080 x0 : 0000000000000000
> [ 2558.207098]
> [ 2558.208565] Process cc1 (pid: 22837, stack limit =
> 0xffff80006dd9c000)
> [ 2558.215035] Stack: (0xffff80006dd9fec0 to 0xffff80006dda0000)
> [ 2558.220728] fec0: 0000000000000065 0000000000f45000 0000000000000020
> 000000000000000c
> [ 2558.228490] fee0: 000040000b3e1aa0 000040000b402020 0000000020020033
> 000040000b3f1240
> [ 2558.236253] ff00: 0000000000000003 0000000000000005 0000000000000661
> 0000000001347000
> [ 2558.244015] ff20: 000040000b3f1258 000040000b3f1270 000000000000001f
> 000040000ad96dc8
> [ 2558.251778] ff40: 0000000001285050 0000400008acaa10 0000000000000001
> 0000000000000054
> [ 2558.259540] ff60: 000040000b3f1250 0000000000000001 0000000000000001
> 0000000000000000
> [ 2558.267303] ff80: 000040000b3f1240 0000000000f58f88 000040000b3f1288
> 00000000012a7000
> [ 2558.275065] ffa0: 000040000b3f1240 0000fffff3ee5f80 00000000006a0e54
> 0000fffff3ee5f80
> [ 2558.282828] ffc0: 00000000006a0d98 0000000080000000 0000000000000003
> ffffffffffffffff
> [ 2558.290590] ffe0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2558.298351] Call trace:
> [ 2558.300769] Exception stack(0xffff80006dd9fcf0 to
> 0xffff80006dd9fe20)
> [ 2558.307149] fce0: 0000000000000000
> 0001000000000000
> [ 2558.314913] fd00: ffff80006dd9fec0 00000000006a0e54 ffff800073acf500
> 0000000000000004
> [ 2558.322675] fd20: 0000000000000000 ffff000008dbbc18 ffff80006ddb7080
> 000000006dd9fdd0
> [ 2558.330438] fd40: ffff80006dd9fd90 ffff0000080ca878 ffff80006dd9fe40
> ffff80006ddb7080
> [ 2558.338200] fd60: 0000000000000004 00000000000003c0 ffff80006dd9fe40
> 000040000b3f1240
> [ 2558.345963] fd80: 0000000000f58f88 000040000b3f1288 0000000000000000
> ffff80006ddb7080
> [ 2558.353725] fda0: 000000000000020f 0000000000000000 0000000000000000
> 00000000020f020e
> [ 2558.361487] fdc0: 000000000000020e 0000000000000000 0000000000010a8b
> ffff80006dd9fb40
> [ 2558.369250] fde0: 00000000000002ea 0000000000000002 000000000000000f
> ffff000008e91f15
> [ 2558.377012] fe00: 0000000000000006 ffff000088e91f07 0000000001285050
> 0000400008acaa10
> [ 2558.384775] [<00000000006a0e54>] 0x6a0e54
> [ 2558.388743] Code: d503201f f9400280 2a1703e1 97ffff0a (aa0003f3)
> [ 2558.395241] ---[ end trace 7d280955c14d4ff1 ]---
> [ 2558.584022] Bad mode in Error handler detected on CPU0, code
> 0xbf000000 -- SError
> [ 2558.585871] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2558.595527] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2558.600444] task: ffff80007454d780 task.stack: ffff8000660bc000
> [ 2558.606310] PC is at 0x631928
> [ 2558.609240] LR is at 0xb59ce0
> [ 2558.612172] pc : [<0000000000631928>] lr : [<0000000000b59ce0>]
> pstate: 80000000
> [ 2558.619503] sp : 0000ffffed764d90
> [ 2558.622782] x29: 0000ffffed764d90 x28: 0000000000000028
> [ 2558.628042] x27: 000000001a1062f0 x26: 0000000001299198
> [ 2558.633303] x25: 0000000000000001 x24: 0000000000000000
> [ 2558.638564] x23: 0000000000000004 x22: 00000000013513c8
> [ 2558.643825] x21: 0000400039d43488 x20: 0000000000000000
> [ 2558.649086] x19: 0000400039d2d730 x18: 0000000000000000
> [ 2558.654348] x17: 0000400039a7c378 x16: 0000000001285138
> [ 2558.659609] x15: 0000000000000001 x14: 0000000000000000
> [ 2558.664870] x13: ffffff0000000000 x12: 0000000000000000
> [ 2558.670131] x11: 0000000000000028 x10: 000000000129b2b8
> [ 2558.675393] x9 : 0000000000000041 x8 : 0000000000000003
> [ 2558.680654] x7 : 0000000000000050 x6 : 000000000003d2c8
> [ 2558.685915] x5 : 0000000000000002 x4 : 0000000000000004
> [ 2558.691176] x3 : 0000000000000003 x2 : 0000000001349000
> [ 2558.696438] x1 : 000000000003cb90 x0 : 0000400039d45050
> [ 2558.701699]
> [ 2558.703177] Internal error: Attempting to execute userspace memory:
> 8600000f [#8] PREEMPT SMP
> [ 2558.711618] Modules linked in: meson_rng rng_core meson_gxbb_wdt
> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
> stmmac_platform stmmac
> [ 2558.724731] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2558.734388] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2558.739304] task: ffff80007454d780 task.stack: ffff8000660bc000
> [ 2558.745169] PC is at 0xb59ce0
> [ 2558.748102] LR is at 0xb59ce0
> [ 2558.751035] pc : [<0000000000b59ce0>] lr : [<0000000000b59ce0>]
> pstate: 600003c5
> [ 2558.758365] sp : ffff8000660bfec0
> [ 2558.761643] x29: 0000000000000000 x28: ffff80007454d780
> [ 2558.766904] x27: 000000001a1062f0 x26: 0000000001299198
> [ 2558.772165] x25: 0000000000000001 x24: 0000000000000000
> [ 2558.777426] x23: 0000000080000000 x22: 0000000000631928
> [ 2558.782688] x21: ffffffffffffffff x20: 000080006e223000
> [ 2558.787949] x19: 0000000000000000 x18: 0000000000000010
> [ 2558.793210] x17: 0000400039a7c378 x16: 0000000001285138
> [ 2558.798471] x15: ffff000088e91f07 x14: 0000000000000006
> [ 2558.803733] x13: ffff000008e91f15 x12: 000000000000000f
> [ 2558.808994] x11: 0000000000000002 x10: 0000000000000336
> [ 2558.814255] x9 : ffff8000660bfb40 x8 : 00000000000ab503
> [ 2558.819516] x7 : 0000000000000000 x6 : 00000000000000dd
> [ 2558.824778] x5 : 0000000000de00dd x4 : 0000000000000000
> [ 2558.830039] x3 : 0000000000000000 x2 : 00000000000000de
> [ 2558.835300] x1 : ffff80007454d780 x0 : 0000000000000000
> [ 2558.840561]
> [ 2558.842029] Process cc1 (pid: 22867, stack limit =
> 0xffff8000660bc000)
> [ 2558.848498] Stack: (0xffff8000660bfec0 to 0xffff8000660c0000)
> [ 2558.854191] fec0: 0000400039d45050 000000000003cb90 0000000001349000
> 0000000000000003
> [ 2558.861953] fee0: 0000000000000004 0000000000000002 000000000003d2c8
> 0000000000000050
> [ 2558.869716] ff00: 0000000000000003 0000000000000041 000000000129b2b8
> 0000000000000028
> [ 2558.877478] ff20: 0000000000000000 ffffff0000000000 0000000000000000
> 0000000000000001
> [ 2558.885241] ff40: 0000000001285138 0000400039a7c378 0000000000000000
> 0000400039d2d730
> [ 2558.893003] ff60: 0000000000000000 0000400039d43488 00000000013513c8
> 0000000000000004
> [ 2558.900766] ff80: 0000000000000000 0000000000000001 0000000001299198
> 000000001a1062f0
> [ 2558.908529] ffa0: 0000000000000028 0000ffffed764d90 0000000000b59ce0
> 0000ffffed764d90
> [ 2558.916291] ffc0: 0000000000631928 0000000080000000 000000001a18c000
> ffffffffffffffff
> [ 2558.924053] ffe0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2558.931814] Call trace:
> [ 2558.934232] Exception stack(0xffff8000660bfcf0 to
> 0xffff8000660bfe20)
> [ 2558.940613] fce0: 0000000000000000
> 0001000000000000
> [ 2558.948376] fd00: ffff8000660bfec0 0000000000b59ce0 ffff800073acf640
> 0000000000000004
> [ 2558.956138] fd20: 0000000000000000 ffff000008dbbc18 ffff80007454d780
> 00000000660bfdd0
> [ 2558.963901] fd40: ffff8000660bfd90 ffff0000080ca878 ffff8000660bfe40
> ffff80007454d780
> [ 2558.971663] fd60: 0000000000000004 00000000000003c0 ffff8000660bfe40
> 0000000000000000
> [ 2558.979426] fd80: 0000000000000001 0000000001299198 0000000000000000
> ffff80007454d780
> [ 2558.987188] fda0: 00000000000000de 0000000000000000 0000000000000000
> 0000000000de00dd
> [ 2558.994951] fdc0: 00000000000000dd 0000000000000000 00000000000ab503
> ffff8000660bfb40
> [ 2559.002713] fde0: 0000000000000336 0000000000000002 000000000000000f
> ffff000008e91f15
> [ 2559.010476] fe00: 0000000000000006 ffff000088e91f07 0000000001285138
> 0000400039a7c378
> [ 2559.018238] [<0000000000b59ce0>] 0xb59ce0
> [ 2559.022207] Code: d2800001 d2800002 d2800500 97eb5e9d (a9007c1f)
> [ 2559.028376] ---[ end trace 7d280955c14d4ff2 ]---
> [ 2559.034397] Bad mode in Error handler detected on CPU2, code
> 0xbf000000 -- SError
> [ 2559.040235] CPU: 2 PID: 22866 Comm: gcc Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2559.049892] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2559.054808] task: ffff80007454e400 task.stack: ffff80006de9c000
> [ 2559.060674] PC is at 0x40003c0400d8
> [ 2559.064122] LR is at 0x46d4e0
> [ 2559.067055] pc : [<000040003c0400d8>] lr : [<000000000046d4e0>]
> pstate: 80000000
> [ 2559.074385] sp : 0000ffffe6387270
> [ 2559.077664] x29: 0000ffffe6387270 x28: 0000000016c0ff90
> [ 2559.082924] x27: 0000000000000002 x26: 0000000000000001
> [ 2559.088185] x25: 0000ffffe63873f4 x24: 0000ffffe63873f8
> [ 2559.093447] x23: 0000ffffe63873f4 x22: 0000ffffe63873f8
> [ 2559.098708] x21: 0000000016c104e0 x20: 0000000000005953
> [ 2559.103969] x19: 0000000000000000 [ 2559.107102] Unhandled fault:
> synchronous external abort (0x96000010) at 0xffff800000c1e000
> [ 2559.107108] Internal error: : 96000010 [#9] PREEMPT SMP
> [ 2559.107110] Modules linked in:
> [ 2559.107113] meson_rng rng_core meson_gxbb_wdt ip_tables x_tables
> ipv6 dwmac_generic realtek dwmac_meson8b stmmac_platform stmmac[
> 2559.107131] CPU: 0 PID: 1124 Comm: mmcqd/1 Tainted: G D 1
> [ 2559.107132] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2559.107135] task: ffff8000704abe80 task.stack: ffff8000734d0000
> [ 2559.107147] PC is at __memcpy+0x100/0x180
> [ 2559.107152] LR is at sg_copy_buffer+0xb0/0x110
> [ 2559.107155] pc : [<ffff00000837ee00>] lr : [<ffff00000838e928>]
> pstate: 200001c5
> [ 2559.107155] sp : ffff8000734d3bb0
> [ 2559.107157] x29: ffff8000734d3bb0
> [ 2559.107158] x28: ffff800073a14800 x27: ffff800073a14b68
> [ 2559.107162] x26: 0000000000000000 x25: 0000000000000140
> [ 2559.107165] x24: 0000000000000001 x23: 0000000000001000
> [ 2559.107168] x22: ffff8000746a2000 x21: 0000000000001000
> [ 2559.107170] x20: 0000000000000000 x19: 0000000000001000
> [ 2559.107172] x18: 0000000000000000 x17: ffffffffffffffff
> [ 2559.107175] x16: 00000000000006be x15: ffff000008c34000
> [ 2559.107178] x14: 747962342e090a34 x13: 3278302038323162
> [ 2559.107181] x12: 656c752e090a3864 x11: ffff800073866800
> [ 2559.107183] x10: ffff80006bf68eb0 x9 : 0000000000000000
> [ 2559.107186] x8 : ffff800073a94920 x7 : 0000000000000000
> [ 2559.107188] x6 : ffff8000746a2000 x5 : 0000820000000000
> [ 2559.107191] x4 : 0000000000000000 x3 : 0000000000000000
> [ 2559.107193] x2 : 0000000000000f80 x1 : ffff800000c1e000
> [ 2559.107196] x0 : ffff8000746a2000
> [ 2559.107199] Process mmcqd/1 (pid: 1124, stack limit =
> 0xffff8000734d0000)
> [ 2559.107202] Stack: (0xffff8000734d3bb0 to 0xffff8000734d4000)
> [ 2559.107205] 3ba0: ffff8000734d3c50
> ffff00000838e9bc
> [ 2559.107208] 3bc0: ffff800073a14000 ffff800073a14a30 ffff80006bf68eb0
> ffff800073a14a28
> [ 2559.107212] 3be0: ffff800073a14818 ffff800073a14800 0000000000000000
> ffff00000838e1c4
> [ 2559.107215] 3c00: ffff800073a94900 ffff7e0000030780 ffff800000c1e000
> 0000000000001000
> [ 2559.107218] 3c20: 0000000000001000 ffff800073ad0a00 0000000100000000
> 0000000000000001
> [ 2559.107221] 3c40: 0000100000000000 0000000000000005 ffff8000734d3c60
> ffff00000874c1bc
> [ 2559.107224] 3c60: ffff8000734d3c70 ffff000008748010 ffff8000734d3cd0
> ffff000008749908
> [ 2559.107228] 3c80: ffff80006bf68eb0 ffff800073a14000 ffff8000734c8000
> ffff800073a14818
> [ 2559.107231] 3ca0: ffff800073a14800 ffff800073a14800 ffff80006bf68eb0
> ffff800073a14a28
> [ 2559.107234] 3cc0: ffff80006bf68eb0 ffff000008749bc8 ffff8000734d3d70
> ffff00000874b298
> [ 2559.107237] 3ce0: ffff800073a14000 ffff800073a14818 ffff8000734c8000
> 0000000000000000
> [ 2559.107240] 3d00: ffff800073a14800 ffff800073a14800 ffff800073a13800
> 0000000000000000
> [ 2559.107243] 3d20: ffff80006bf68eb0 0000000000000000 00000000012853f0
> ffff000008c0fcb8
> [ 2559.107246] 3d40: 0000000000000000 000000000835bf14 ffff000008a05f58
> ffff800000000000
> [ 2559.107249] 3d60: ffff8000734c8000 0000000000000001 ffff8000734d3de0
> ffff00000874b6f4
> [ 2559.107252] 3d80: ffff800073a14818 ffff80006bf68eb0 ffff8000734c8000
> 0000000000000001
> [ 2559.107255] 3da0: ffff800073a14828 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107258] 3dc0: 0000000000000000 0000000000000000 ffff800073a14818
> ffff00000874b6c4
> [ 2559.107261] 3de0: ffff8000734d3e20 ffff0000080daa84 ffff800073a94980
> ffff000008e8eb08
> [ 2559.107264] 3e00: ffff000008b75b50 ffff800073a14818 ffff00000874b658
> 0000000000000000
> [ 2559.107267] 3e20: 0000000000000000 ffff000008082ec0 ffff0000080da9b8
> ffff800073a94980
> [ 2559.107270] 3e40: 0000000000000000 0000000000000000 0000000000000000
> 000003ff01893600
> [ 2559.107273] 3e60: ffff8000734d3ea0 0000000000000000 ffff0000080da9b8
> ffff800073a14818
> [ 2559.107276] 3e80: 0000000000000000 0000000000000000 ffff8000734d3e90
> ffff8000734d3e90
> [ 2559.107279] 3ea0: 0000000000000000 ffff000000000000 ffff8000734d3eb0
> ffff8000734d3eb0
> [ 2559.107281] 3ec0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107284] 3ee0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107287] 3f00: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107290] 3f20: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107293] 3f40: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107295] 3f60: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107298] 3f80: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107300] 3fa0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107303] 3fc0: 0000000000000000 0000000000000005 0000000000000000
> 0000000000000000
> [ 2559.107306] 3fe0: 0000000000000000 0000000000000000 0000001800002cba
> 26000000a01b3800
> [ 2559.107308] Call trace:
> [ 2559.107312] Exception stack(0xffff8000734d39e0 to
> 0xffff8000734d3b10)
> [ 2559.107315] 39e0: 0000000000001000 0001000000000000 ffff8000734d3bb0
> ffff00000837ee00
> [ 2559.107318] 3a00: 0000000000000007 ffff800000000000 ffff800000c1e000
> 0000000100100010
> [ 2559.107321] 3a20: ffff8000734d3ac0 ffff000008748d88 ffff8000734d3b8c
> 0000000000000001
> [ 2559.107324] 3a40: ffff8000734d3b40 ffff0000081c9dac ffff800074401d00
> ffff0000081745d8
> [ 2559.107327] 3a60: ffff7e0001b72f80 ffff80006dcbe300 00000000031fda40
> 0000000000000000
> [ 2559.107330] 3a80: ffff8000746a2000 ffff800000c1e000 0000000000000f80
> 0000000000000000
> [ 2559.107333] 3aa0: 0000000000000000 0000820000000000 ffff8000746a2000
> 0000000000000000
> [ 2559.107336] 3ac0: ffff800073a94920 0000000000000000 ffff80006bf68eb0
> ffff800073866800
> [ 2559.107339] 3ae0: 656c752e090a3864 3278302038323162 747962342e090a34
> ffff000008c34000
> [ 2559.107341] 3b00: 00000000000006be ffffffffffffffff
> [ 2559.107346] [<ffff00000837ee00>] __memcpy+0x100/0x180
> [ 2559.107349] [<ffff00000838e9bc>] sg_copy_to_buffer+0x14/0x20
> [ 2559.107357] [<ffff00000874c1bc>] mmc_queue_bounce_pre+0x34/0x40
> [ 2559.107362] [<ffff000008748010>] mmc_blk_rw_rq_prep+0x288/0x3a0
> [ 2559.107365] [<ffff000008749908>] mmc_blk_issue_rw_rq+0x3c0/0x998
> [ 2559.107368] [<ffff00000874b298>] mmc_blk_issue_rq+0x150/0x510
> [ 2559.107371] [<ffff00000874b6f4>] mmc_queue_thread+0x9c/0x140
> [ 2559.107377] [<ffff0000080daa84>] kthread+0xcc/0xe0
> [ 2559.107383] [<ffff000008082ec0>] ret_from_fork+0x10/0x50
Looks like it died whilst processing an mmc request.
^ permalink raw reply
* mmc: core: complete/wait_for_completion performance
From: Stefan Wahren @ 2016-11-26 19:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479669034.1975.1.camel@embedded.rocks>
Hi J?rg,
> J?rg Krause <joerg.krause@embedded.rocks> hat am 20. November 2016 um 20:10
> geschrieben:
>
>
> On Sun, 2016-11-20 at 16:44 +0100, Stefan Wahren wrote:
> > > J?rg Krause <joerg.krause@embedded.rocks> hat am 20. November 2016
> > > um 15:42
> > > geschrieben:
> > >
> > >
> > > Hi Stefan,
> > >
> > > On Sun, 2016-11-20 at 14:28 +0100, Stefan Wahren wrote:
> > > > Hi J?rg,
> > > >
> > > > > J?rg Krause <joerg.krause@embedded.rocks> hat am 20. November
> > > > > 2016
> > > > > um 13:27
> > > > > geschrieben:
> > > > >
> > > > >
> > > > > Hi,
> > > > >
> > > > > I started the discussion on this mailing list in another thread
> > > > > [1],
> > > > > but I'd like to move it to a new thread, because it might be
> > > > > mmc
> > > > > specific.
> > > > >
> > > > > The issue is that I am noticed low wifi network throughput on
> > > > > an
> > > > > i.MX28
> > > > > board with the mainline kernel (v4.7.10, about 6 Mbps) compared
> > > > > to
> > > > > the
> > > > > vendor kernel (Freescale v2.6.35.3, about 20 Mbps). The wifi
> > > > > chip
> > > > > is
> > > > > attached using the SDIO interface.
> > > > >
> > > > > I started investigation where the bottleneck in the mainline
> > > > > kernel?might come from. Therefore I checked that the configs
> > > > > and
> > > > > settings for the interfaces and drivers are the same. They are.
> > > >
> > > > so you're not using the mxs_defconfig settings anymore?
> > >
> > > No, I changed the settings.
> > >
> >
> > What happens to performance to if you change the following settings
> > to the same
> > like in mxs_defconfig?
> >
> > CONFIG_PREEMPT_VOLUNTARY=y
> > CONFIG_DEFAULT_IOSCHED="noop"
>
> No much change at all. The time difference between complete() and
> wait_for_complete() decreases in best case to 110 us, but also varies
> to above 130 us.
just a weird idea. Did you tried to add MMC_CAP_CMD23 into the caps [1]?
[1] - http://lxr.free-electrons.com/source/drivers/mmc/host/mxs-mmc.c?v=4.8#L642
^ permalink raw reply
* [PATCH 0/2] CRC32 for ARM and arm64 using PMULL and CRC instructions
From: Ard Biesheuvel @ 2016-11-26 20:15 UTC (permalink / raw)
To: linux-arm-kernel
Version 8 of the ARM architecture introduces both a set of dedicated CRC32
instructions, and a 64x64 to 128 bit polynomial multiplication instruction,
both of which can be used to accelerate CRC32 calculations.
These patches contains ports of the existing polynomial multiplication based
CRC32 code that resides in arch/x86/crypto/crc32-pclmul_asm.S, but since that
algorithm operates on multiples of 16 bytes only, and requires at least 64
bytes of input, the remainders are calculated with the CRC32 instructions,
if available.
These patches apply on top of the CRC-T10DIF series I sent out last Thursday.
https://git.kernel.org/cgit/linux/kernel/git/ardb/linux.git/log/?h=crc32
Ard Biesheuvel (2):
crypto: arm64/crc32 - accelerated support based on x86 SSE
implementation
crypto: arm/crc32 - accelerated support based on x86 SSE
implementation
arch/arm/crypto/Kconfig | 5 +
arch/arm/crypto/Makefile | 2 +
arch/arm/crypto/crc32-ce-core.S | 257 ++++++++++++++++++++
arch/arm/crypto/crc32-ce-glue.c | 129 ++++++++++
arch/arm64/crypto/Kconfig | 6 +
arch/arm64/crypto/Makefile | 3 +
arch/arm64/crypto/crc32-ce-core.S | 246 +++++++++++++++++++
arch/arm64/crypto/crc32-ce-glue.c | 124 ++++++++++
8 files changed, 772 insertions(+)
create mode 100644 arch/arm/crypto/crc32-ce-core.S
create mode 100644 arch/arm/crypto/crc32-ce-glue.c
create mode 100644 arch/arm64/crypto/crc32-ce-core.S
create mode 100644 arch/arm64/crypto/crc32-ce-glue.c
--
2.7.4
^ permalink raw reply
* [PATCH 1/2] crypto: arm64/crc32 - accelerated support based on x86 SSE implementation
From: Ard Biesheuvel @ 2016-11-26 20:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480191314-2331-1-git-send-email-ard.biesheuvel@linaro.org>
This is a combination of the the Intel algorithm implemented using SSE
and PCLMULQDQ instructions from arch/x86/crypto/crc32-pclmul_asm.S, and
the new CRC32 extensions introduced for both 32-bit and 64-bit ARM in
version 8 of the architecture.
The PMULL/NEON algorithm is faster, but operates on blocks of at least
64 bytes, and on multiples of 16 bytes only. For the remaining input,
or for all input on systems that lack the PMULL 64x64->128 instructions,
the CRC32 instructions will be used.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm64/crypto/Kconfig | 6 +
arch/arm64/crypto/Makefile | 3 +
arch/arm64/crypto/crc32-ce-core.S | 246 ++++++++++++++++++++
arch/arm64/crypto/crc32-ce-glue.c | 124 ++++++++++
4 files changed, 379 insertions(+)
diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
index 1b50671ffec3..11dc2ac1f2e5 100644
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -58,4 +58,10 @@ config CRYPTO_CRC32_ARM64
tristate "CRC32 and CRC32C using optional ARMv8 instructions"
depends on ARM64
select CRYPTO_HASH
+
+config CRYPTO_CRC32_ARM64_CE
+ tristate "CRC32 digest algorithm using PMULL instructions"
+ depends on ARM64 && KERNEL_MODE_NEON
+ select CRYPTO_HASH
+
endif
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index 36fd3eb4201b..144387805a46 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -20,6 +20,9 @@ ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM64_CE) += crct10dif-ce.o
crct10dif-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o
+obj-$(CONFIG_CRYPTO_CRC32_ARM64_CE) += crc32-ce.o
+crc32-ce-y:= crc32-ce-core.o crc32-ce-glue.o
+
obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o
CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto
diff --git a/arch/arm64/crypto/crc32-ce-core.S b/arch/arm64/crypto/crc32-ce-core.S
new file mode 100644
index 000000000000..eff7fe100dab
--- /dev/null
+++ b/arch/arm64/crypto/crc32-ce-core.S
@@ -0,0 +1,246 @@
+/*
+ * Accelerated CRC32 using arm64 CRC, NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see http://www.gnu.org/licenses
+ *
+ * Please visit http://www.xyratex.com/contact if you need additional
+ * information or have any questions.
+ *
+ * GPL HEADER END
+ */
+
+/*
+ * Copyright 2012 Xyratex Technology Limited
+ *
+ * Using hardware provided PCLMULQDQ instruction to accelerate the CRC32
+ * calculation.
+ * CRC32 polynomial:0x04c11db7(BE)/0xEDB88320(LE)
+ * PCLMULQDQ is a new instruction in Intel SSE4.2, the reference can be found
+ * at:
+ * http://www.intel.com/products/processor/manuals/
+ * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 2B: Instruction Set Reference, N-Z
+ *
+ * Authors: Gregory Prestas <Gregory_Prestas@us.xyratex.com>
+ * Alexander Boyko <Alexander_Boyko@xyratex.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+
+ .text
+ .align 4
+ .cpu generic+crypto+crc
+
+ /*
+ * [x4*128+32 mod P(x) << 32)]' << 1 = 0x154442bd4
+ * #define CONSTANT_R1 0x154442bd4LL
+ *
+ * [(x4*128-32 mod P(x) << 32)]' << 1 = 0x1c6e41596
+ * #define CONSTANT_R2 0x1c6e41596LL
+ */
+.Lconstant_R2R1:
+ .octa 0x00000001c6e415960000000154442bd4
+
+ /*
+ * [(x128+32 mod P(x) << 32)]' << 1 = 0x1751997d0
+ * #define CONSTANT_R3 0x1751997d0LL
+ *
+ * [(x128-32 mod P(x) << 32)]' << 1 = 0x0ccaa009e
+ * #define CONSTANT_R4 0x0ccaa009eLL
+ */
+.Lconstant_R4R3:
+ .octa 0x00000000ccaa009e00000001751997d0
+
+ /*
+ * [(x64 mod P(x) << 32)]' << 1 = 0x163cd6124
+ * #define CONSTANT_R5 0x163cd6124LL
+ */
+.Lconstant_R5:
+ .octa 0x00000000000000000000000163cd6124
+.Lconstant_mask32:
+ .octa 0x000000000000000000000000FFFFFFFF
+
+ /*
+ * #define CRCPOLY_TRUE_LE_FULL 0x1DB710641LL
+ *
+ * Barrett Reduction constant (u64`) = u` = (x**64 / P(x))`
+ * = 0x1F7011641LL
+ * #define CONSTANT_RU 0x1F7011641LL
+ */
+.Lconstant_RUpoly:
+ .octa 0x00000001F701164100000001DB710641
+
+ vCONSTANT .req v0
+ dCONSTANT .req d0
+ qCONSTANT .req q0
+
+ BUF .req x0
+ LEN .req x1
+ CRC .req x2
+
+ vzr .req v9
+
+ /**
+ * Calculate crc32
+ * BUF - buffer
+ * LEN - sizeof buffer (multiple of 16 bytes), LEN should be > 63
+ * CRC - initial crc32
+ * return %eax crc32
+ * uint crc32_pmull_le(unsigned char const *buffer,
+ * size_t len, uint crc32)
+ */
+ENTRY(crc32_pmull_le)
+ bic LEN, LEN, #15
+ ld1 {v1.16b-v4.16b}, [BUF], #0x40
+ movi vzr.16b, #0
+ fmov dCONSTANT, CRC
+ eor v1.16b, v1.16b, vCONSTANT.16b
+ sub LEN, LEN, #0x40
+ cmp LEN, #0x40
+ b.lt less_64
+
+ ldr qCONSTANT, .Lconstant_R2R1
+
+loop_64: /* 64 bytes Full cache line folding */
+ sub LEN, LEN, #0x40
+
+ pmull2 v5.1q, v1.2d, vCONSTANT.2d
+ pmull2 v6.1q, v2.2d, vCONSTANT.2d
+ pmull2 v7.1q, v3.2d, vCONSTANT.2d
+ pmull2 v8.1q, v4.2d, vCONSTANT.2d
+
+ pmull v1.1q, v1.1d, vCONSTANT.1d
+ pmull v2.1q, v2.1d, vCONSTANT.1d
+ pmull v3.1q, v3.1d, vCONSTANT.1d
+ pmull v4.1q, v4.1d, vCONSTANT.1d
+
+ eor v1.16b, v1.16b, v5.16b
+ ld1 {v5.16b}, [BUF], #0x10
+ eor v2.16b, v2.16b, v6.16b
+ ld1 {v6.16b}, [BUF], #0x10
+ eor v3.16b, v3.16b, v7.16b
+ ld1 {v7.16b}, [BUF], #0x10
+ eor v4.16b, v4.16b, v8.16b
+ ld1 {v8.16b}, [BUF], #0x10
+
+ eor v1.16b, v1.16b, v5.16b
+ eor v2.16b, v2.16b, v6.16b
+ eor v3.16b, v3.16b, v7.16b
+ eor v4.16b, v4.16b, v8.16b
+
+ cmp LEN, #0x40
+ b.ge loop_64
+
+less_64: /* Folding cache line into 128bit */
+ ldr qCONSTANT, .Lconstant_R4R3
+
+ pmull2 v5.1q, v1.2d, vCONSTANT.2d
+ pmull v1.1q, v1.1d, vCONSTANT.1d
+ eor v1.16b, v1.16b, v5.16b
+ eor v1.16b, v1.16b, v2.16b
+
+ pmull2 v5.1q, v1.2d, vCONSTANT.2d
+ pmull v1.1q, v1.1d, vCONSTANT.1d
+ eor v1.16b, v1.16b, v5.16b
+ eor v1.16b, v1.16b, v3.16b
+
+ pmull2 v5.1q, v1.2d, vCONSTANT.2d
+ pmull v1.1q, v1.1d, vCONSTANT.1d
+ eor v1.16b, v1.16b, v5.16b
+ eor v1.16b, v1.16b, v4.16b
+
+ cbz LEN, fold_64
+
+loop_16: /* Folding rest buffer into 128bit */
+ subs LEN, LEN, #0x10
+
+ ld1 {v2.16b}, [BUF], #0x10
+ pmull2 v5.1q, v1.2d, vCONSTANT.2d
+ pmull v1.1q, v1.1d, vCONSTANT.1d
+ eor v1.16b, v1.16b, v5.16b
+ eor v1.16b, v1.16b, v2.16b
+
+ b.ne loop_16
+
+fold_64:
+ /* perform the last 64 bit fold, also adds 32 zeroes
+ * to the input stream */
+ ext v2.16b, v1.16b, v1.16b, #8
+ pmull2 v2.1q, v2.2d, vCONSTANT.2d
+ ext v1.16b, v1.16b, vzr.16b, #8
+ eor v1.16b, v1.16b, v2.16b
+
+ /* final 32-bit fold */
+ ldr qCONSTANT, .Lconstant_R5
+ ldr q3, .Lconstant_mask32
+
+ ext v2.16b, v1.16b, vzr.16b, #4
+ and v1.16b, v1.16b, v3.16b
+ pmull v1.1q, v1.1d, vCONSTANT.1d
+ eor v1.16b, v1.16b, v2.16b
+
+ /* Finish up with the bit-reversed barrett reduction 64 ==> 32 bits */
+ ldr qCONSTANT, .Lconstant_RUpoly
+
+ and v2.16b, v1.16b, v3.16b
+ ext v2.16b, vzr.16b, v2.16b, #8
+ pmull2 v2.1q, v2.2d, vCONSTANT.2d
+ and v2.16b, v2.16b, v3.16b
+ pmull v2.1q, v2.1d, vCONSTANT.1d
+ eor v1.16b, v1.16b, v2.16b
+ mov w0, v1.s[1]
+
+ ret
+ENDPROC(crc32_pmull_le)
+
+ENTRY(crc32_armv8_le)
+0: subs x2, x2, #16
+ b.mi 8f
+ ldp x3, x4, [x1], #16
+CPU_BE( rev x3, x3 )
+CPU_BE( rev x4, x4 )
+ crc32x w0, w0, x3
+ crc32x w0, w0, x4
+ b 0b
+
+8: tbz x2, #3, 4f
+ ldr x3, [x1], #8
+CPU_BE( rev x3, x3 )
+ crc32x w0, w0, x3
+4: tbz x2, #2, 2f
+ ldr w3, [x1], #4
+CPU_BE( rev w3, w3 )
+ crc32w w0, w0, w3
+2: tbz x2, #1, 1f
+ ldrh w3, [x1], #2
+CPU_BE( rev16 w3, w3 )
+ crc32h w0, w0, w3
+1: tbz x2, #0, 0f
+ ldrb w3, [x1]
+ crc32b w0, w0, w3
+0: ret
+ENDPROC(crc32_armv8_le)
diff --git a/arch/arm64/crypto/crc32-ce-glue.c b/arch/arm64/crypto/crc32-ce-glue.c
new file mode 100644
index 000000000000..567203f29ac6
--- /dev/null
+++ b/arch/arm64/crypto/crc32-ce-glue.c
@@ -0,0 +1,124 @@
+/*
+ * Accelerated CRC32 using arm64 NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/cpufeature.h>
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/unaligned.h>
+
+#define PMULL_MIN_LEN 64L /* minimum size of buffer
+ * for crc32_pmull_le_16 */
+#define SCALE_F 16L /* size of NEON register */
+
+asmlinkage u32 crc32_pmull_le(const u8 buf[], u64 len, u32 init_crc);
+asmlinkage u32 crc32_armv8_le(u32 init_crc, const u8 buf[], u64 len);
+
+static int crc32_pmull_cra_init(struct crypto_tfm *tfm)
+{
+ u32 *key = crypto_tfm_ctx(tfm);
+
+ *key = 0;
+ return 0;
+}
+
+static int crc32_pmull_setkey(struct crypto_shash *hash, const u8 *key,
+ unsigned int keylen)
+{
+ u32 *mctx = crypto_shash_ctx(hash);
+
+ if (keylen != sizeof(u32)) {
+ crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+ *mctx = le32_to_cpup((__le32 *)key);
+ return 0;
+}
+
+static int crc32_pmull_init(struct shash_desc *desc)
+{
+ u32 *mctx = crypto_shash_ctx(desc->tfm);
+ u32 *crc = shash_desc_ctx(desc);
+
+ *crc = *mctx;
+ return 0;
+}
+
+static int crc32_pmull_update(struct shash_desc *desc, const u8 *data,
+ unsigned int length)
+{
+ u32 *crc = shash_desc_ctx(desc);
+
+ if (length >= PMULL_MIN_LEN) {
+ kernel_neon_begin_partial(10);
+ *crc = crc32_pmull_le(data, round_down(length, SCALE_F), *crc);
+ kernel_neon_end();
+
+ data += round_down(length, SCALE_F);
+ length %= SCALE_F;
+ }
+
+ if (length > 0) {
+ if (elf_hwcap & HWCAP_CRC32)
+ *crc = crc32_armv8_le(*crc, data, length);
+ else
+ *crc = crc32_le(*crc, data, length);
+ }
+
+ return 0;
+}
+
+static int crc32_pmull_final(struct shash_desc *desc, u8 *out)
+{
+ u32 *crc = shash_desc_ctx(desc);
+
+ put_unaligned_le32(*crc, out);
+ return 0;
+}
+
+static struct shash_alg crc32_pmull_alg = {
+ .setkey = crc32_pmull_setkey,
+ .init = crc32_pmull_init,
+ .update = crc32_pmull_update,
+ .final = crc32_pmull_final,
+ .descsize = sizeof(u32),
+ .digestsize = sizeof(u32),
+
+ .base.cra_ctxsize = sizeof(u32),
+ .base.cra_init = crc32_pmull_cra_init,
+ .base.cra_name = "crc32",
+ .base.cra_driver_name = "crc32-arm64-ce",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_module = THIS_MODULE,
+};
+
+static int __init crc32_pmull_mod_init(void)
+{
+ return crypto_register_shash(&crc32_pmull_alg);
+}
+
+static void __exit crc32_pmull_mod_exit(void)
+{
+ crypto_unregister_shash(&crc32_pmull_alg);
+}
+
+module_cpu_feature_match(PMULL, crc32_pmull_mod_init);
+module_exit(crc32_pmull_mod_exit);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH 2/2] crypto: arm/crc32 - accelerated support based on x86 SSE implementation
From: Ard Biesheuvel @ 2016-11-26 20:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480191314-2331-1-git-send-email-ard.biesheuvel@linaro.org>
This is a combination of the the Intel algorithm implemented using SSE
and PCLMULQDQ instructions from arch/x86/crypto/crc32-pclmul_asm.S, and
the new CRC32 extensions introduced for both 32-bit and 64-bit ARM in
version 8 of the architecture.
The PMULL/NEON algorithm is faster, but operates on blocks of at least
64 bytes, and on multiples of 16 bytes only. For the remaining input,
or for all input on systems that lack the PMULL 64x64->128 instructions,
the CRC32 instructions will be used.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
arch/arm/crypto/Kconfig | 5 +
arch/arm/crypto/Makefile | 2 +
arch/arm/crypto/crc32-ce-core.S | 257 ++++++++++++++++++++
arch/arm/crypto/crc32-ce-glue.c | 129 ++++++++++
4 files changed, 393 insertions(+)
diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
index fce801fa52a1..be5cb5a7d3fa 100644
--- a/arch/arm/crypto/Kconfig
+++ b/arch/arm/crypto/Kconfig
@@ -125,4 +125,9 @@ config CRYPTO_CRCT10DIF_ARM_CE
depends on KERNEL_MODE_NEON && CRC_T10DIF
select CRYPTO_HASH
+config CRYPTO_CRC32_ARM_CE
+ tristate "CRC32 digest algorithm using CRC and/or PMULL instructions"
+ depends on KERNEL_MODE_NEON && CRC32
+ select CRYPTO_HASH
+
endif
diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile
index fc77265014b7..b578a1820ab1 100644
--- a/arch/arm/crypto/Makefile
+++ b/arch/arm/crypto/Makefile
@@ -14,6 +14,7 @@ ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
ce-obj-$(CONFIG_CRYPTO_SHA2_ARM_CE) += sha2-arm-ce.o
ce-obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
ce-obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM_CE) += crct10dif-arm-ce.o
+ce-obj-$(CONFIG_CRYPTO_CRC32_ARM_CE) += crc32-arm-ce.o
ifneq ($(ce-obj-y)$(ce-obj-m),)
ifeq ($(call as-instr,.fpu crypto-neon-fp-armv8,y,n),y)
@@ -38,6 +39,7 @@ sha2-arm-ce-y := sha2-ce-core.o sha2-ce-glue.o
aes-arm-ce-y := aes-ce-core.o aes-ce-glue.o
ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o
crct10dif-arm-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o
+crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
quiet_cmd_perl = PERL $@
cmd_perl = $(PERL) $(<) > $(@)
diff --git a/arch/arm/crypto/crc32-ce-core.S b/arch/arm/crypto/crc32-ce-core.S
new file mode 100644
index 000000000000..ef671f040672
--- /dev/null
+++ b/arch/arm/crypto/crc32-ce-core.S
@@ -0,0 +1,257 @@
+/*
+ * Accelerated CRC32 using ARM CRC, NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see http://www.gnu.org/licenses
+ *
+ * Please visit http://www.xyratex.com/contact if you need additional
+ * information or have any questions.
+ *
+ * GPL HEADER END
+ */
+
+/*
+ * Copyright 2012 Xyratex Technology Limited
+ *
+ * Using hardware provided PCLMULQDQ instruction to accelerate the CRC32
+ * calculation.
+ * CRC32 polynomial:0x04c11db7(BE)/0xEDB88320(LE)
+ * PCLMULQDQ is a new instruction in Intel SSE4.2, the reference can be found
+ * at:
+ * http://www.intel.com/products/processor/manuals/
+ * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 2B: Instruction Set Reference, N-Z
+ *
+ * Authors: Gregory Prestas <Gregory_Prestas@us.xyratex.com>
+ * Alexander Boyko <Alexander_Boyko@xyratex.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ .text
+ .align 4
+ .arch armv8-a
+ .arch_extension crc
+ .fpu crypto-neon-fp-armv8
+
+ /*
+ * [x4*128+32 mod P(x) << 32)]' << 1 = 0x154442bd4
+ * #define CONSTANT_R1 0x154442bd4LL
+ *
+ * [(x4*128-32 mod P(x) << 32)]' << 1 = 0x1c6e41596
+ * #define CONSTANT_R2 0x1c6e41596LL
+ */
+.Lconstant_R2R1:
+ .quad 0x0000000154442bd4
+ .quad 0x00000001c6e41596
+
+ /*
+ * [(x128+32 mod P(x) << 32)]' << 1 = 0x1751997d0
+ * #define CONSTANT_R3 0x1751997d0LL
+ *
+ * [(x128-32 mod P(x) << 32)]' << 1 = 0x0ccaa009e
+ * #define CONSTANT_R4 0x0ccaa009eLL
+ */
+.Lconstant_R4R3:
+ .quad 0x00000001751997d0
+ .quad 0x00000000ccaa009e
+
+ /*
+ * [(x64 mod P(x) << 32)]' << 1 = 0x163cd6124
+ * #define CONSTANT_R5 0x163cd6124LL
+ */
+.Lconstant_R5:
+ .quad 0x0000000163cd6124
+
+.Lconstant_mask32:
+ .quad 0x00000000FFFFFFFF
+
+ /*
+ * #define CRCPOLY_TRUE_LE_FULL 0x1DB710641LL
+ *
+ * Barrett Reduction constant (u64`) = u` = (x**64 / P(x))`
+ * = 0x1F7011641LL
+ * #define CONSTANT_RU 0x1F7011641LL
+ */
+.Lconstant_RUpoly:
+ .quad 0x00000001DB710641
+ .quad 0x00000001F7011641
+
+ dCONSTANTl .req d0
+ dCONSTANTh .req d1
+ qCONSTANT .req q0
+
+ BUF .req r0
+ LEN .req r1
+ CRC .req r2
+
+ qzr .req q9
+
+ /**
+ * Calculate crc32
+ * BUF - buffer
+ * LEN - sizeof buffer (multiple of 16 bytes), LEN should be > 63
+ * CRC - initial crc32
+ * return %eax crc32
+ * uint crc32_pmull_le(unsigned char const *buffer,
+ * size_t len, uint crc32)
+ */
+ENTRY(crc32_pmull_le)
+ bic LEN, LEN, #15
+ vld1.8 {q1-q2}, [BUF]!
+ vld1.8 {q3-q4}, [BUF]!
+ vmov.i8 qzr, #0
+ vmov.i8 qCONSTANT, #0
+ vmov dCONSTANTl[0], CRC
+ veor.8 d2, d2, dCONSTANTl
+ sub LEN, LEN, #0x40
+ cmp LEN, #0x40
+ blt less_64
+
+ vldr dCONSTANTl, .Lconstant_R2R1
+ vldr dCONSTANTh, .Lconstant_R2R1 + 8
+
+loop_64: /* 64 bytes Full cache line folding */
+ sub LEN, LEN, #0x40
+
+ vmull.p64 q5, d3, dCONSTANTh
+ vmull.p64 q6, d5, dCONSTANTh
+ vmull.p64 q7, d7, dCONSTANTh
+ vmull.p64 q8, d9, dCONSTANTh
+
+ vmull.p64 q1, d2, dCONSTANTl
+ vmull.p64 q2, d4, dCONSTANTl
+ vmull.p64 q3, d6, dCONSTANTl
+ vmull.p64 q4, d8, dCONSTANTl
+
+ veor.8 q1, q1, q5
+ vld1.8 {q5}, [BUF]!
+ veor.8 q2, q2, q6
+ vld1.8 {q6}, [BUF]!
+ veor.8 q3, q3, q7
+ vld1.8 {q7}, [BUF]!
+ veor.8 q4, q4, q8
+ vld1.8 {q8}, [BUF]!
+
+ veor.8 q1, q1, q5
+ veor.8 q2, q2, q6
+ veor.8 q3, q3, q7
+ veor.8 q4, q4, q8
+
+ cmp LEN, #0x40
+ bge loop_64
+
+less_64: /* Folding cache line into 128bit */
+ vldr dCONSTANTl, .Lconstant_R4R3
+ vldr dCONSTANTh, .Lconstant_R4R3 + 8
+
+ vmull.p64 q5, d3, dCONSTANTh
+ vmull.p64 q1, d2, dCONSTANTl
+ veor.8 q1, q1, q5
+ veor.8 q1, q1, q2
+
+ vmull.p64 q5, d3, dCONSTANTh
+ vmull.p64 q1, d2, dCONSTANTl
+ veor.8 q1, q1, q5
+ veor.8 q1, q1, q3
+
+ vmull.p64 q5, d3, dCONSTANTh
+ vmull.p64 q1, d2, dCONSTANTl
+ veor.8 q1, q1, q5
+ veor.8 q1, q1, q4
+
+ teq LEN, #0
+ beq fold_64
+
+loop_16: /* Folding rest buffer into 128bit */
+ subs LEN, LEN, #0x10
+
+ vld1.8 {q2}, [BUF]!
+ vmull.p64 q5, d3, dCONSTANTh
+ vmull.p64 q1, d2, dCONSTANTl
+ veor.8 q1, q1, q5
+ veor.8 q1, q1, q2
+
+ bne loop_16
+
+fold_64:
+ /* perform the last 64 bit fold, also adds 32 zeroes
+ * to the input stream */
+ vmull.p64 q2, d2, dCONSTANTh
+ vext.8 q1, q1, qzr, #8
+ veor.8 q1, q1, q2
+
+ /* final 32-bit fold */
+ vldr dCONSTANTl, .Lconstant_R5
+ vldr d6, .Lconstant_mask32
+ vmov.i8 d7, #0
+
+ vext.8 q2, q1, qzr, #4
+ vand.8 d2, d2, d6
+ vmull.p64 q1, d2, dCONSTANTl
+ veor.8 q1, q1, q2
+
+ /* Finish up with the bit-reversed barrett reduction 64 ==> 32 bits */
+ vldr dCONSTANTl, .Lconstant_RUpoly
+ vldr dCONSTANTh, .Lconstant_RUpoly + 8
+
+ vand.8 q2, q1, q3
+ vext.8 q2, qzr, q2, #8
+ vmull.p64 q2, d5, dCONSTANTh
+ vand.8 q2, q2, q3
+ vmull.p64 q2, d4, dCONSTANTl
+ veor.8 q1, q1, q2
+ vmov r0, s5
+
+ bx lr
+ENDPROC(crc32_pmull_le)
+
+ENTRY(crc32_armv8_le)
+ mov ip, r2
+0: subs ip, ip, #8
+ bmi 4f
+ ldrd r2, r3, [r1], #8
+ARM_BE8(rev r2, r2 )
+ARM_BE8(rev r3, r3 )
+ crc32w r0, r0, r2
+ crc32w r0, r0, r3
+ b 0b
+
+4: tst ip, #4
+ beq 2f
+ ldr r3, [r1], #4
+ARM_BE8(rev r3, r3 )
+ crc32w r0, r0, r3
+2: tst ip, #2
+ beq 1f
+ ldrh r3, [r1], #2
+ARM_BE8(rev16 r3, r3 )
+ crc32h r0, r0, r3
+1: tst ip, #1
+ bxeq lr
+ ldrb r3, [r1]
+ crc32b r0, r0, r3
+ bx lr
+ENDPROC(crc32_armv8_le)
diff --git a/arch/arm/crypto/crc32-ce-glue.c b/arch/arm/crypto/crc32-ce-glue.c
new file mode 100644
index 000000000000..61916b6b40e9
--- /dev/null
+++ b/arch/arm/crypto/crc32-ce-glue.c
@@ -0,0 +1,129 @@
+/*
+ * Accelerated CRC32 using ARM CRC, NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <asm/unaligned.h>
+
+#define PMULL_MIN_LEN 64L /* minimum size of buffer
+ * for crc32_pmull_le_16 */
+#define SCALE_F 16L /* size of NEON register */
+
+asmlinkage u32 crc32_pmull_le(const u8 buf[], u32 len, u32 init_crc);
+asmlinkage u32 crc32_armv8_le(u32 init_crc, const u8 buf[], u32 len);
+
+static int crc32_pmull_cra_init(struct crypto_tfm *tfm)
+{
+ u32 *key = crypto_tfm_ctx(tfm);
+
+ *key = 0;
+ return 0;
+}
+
+static int crc32_pmull_setkey(struct crypto_shash *hash, const u8 *key,
+ unsigned int keylen)
+{
+ u32 *mctx = crypto_shash_ctx(hash);
+
+ if (keylen != sizeof(u32)) {
+ crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+ *mctx = le32_to_cpup((__le32 *)key);
+ return 0;
+}
+
+static int crc32_pmull_init(struct shash_desc *desc)
+{
+ u32 *mctx = crypto_shash_ctx(desc->tfm);
+ u32 *crc = shash_desc_ctx(desc);
+
+ *crc = *mctx;
+ return 0;
+}
+
+static int crc32_pmull_update(struct shash_desc *desc, const u8 *data,
+ unsigned int length)
+{
+ u32 *crc = shash_desc_ctx(desc);
+
+ if (length >= PMULL_MIN_LEN && may_use_simd() &&
+ (elf_hwcap2 & HWCAP2_PMULL)) {
+ kernel_neon_begin();
+ *crc = crc32_pmull_le(data, round_down(length, SCALE_F), *crc);
+ kernel_neon_end();
+
+ data += round_down(length, SCALE_F);
+ length %= SCALE_F;
+ }
+
+ if (length > 0) {
+ if (elf_hwcap2 & HWCAP2_CRC32)
+ *crc = crc32_armv8_le(*crc, data, length);
+ else
+ *crc = crc32_le(*crc, data, length);
+ }
+
+ return 0;
+}
+
+static int crc32_pmull_final(struct shash_desc *desc, u8 *out)
+{
+ u32 *crc = shash_desc_ctx(desc);
+
+ put_unaligned_le32(*crc, out);
+ return 0;
+}
+
+static struct shash_alg crc32_pmull_alg = {
+ .setkey = crc32_pmull_setkey,
+ .init = crc32_pmull_init,
+ .update = crc32_pmull_update,
+ .final = crc32_pmull_final,
+ .descsize = sizeof(u32),
+ .digestsize = sizeof(u32),
+
+ .base.cra_ctxsize = sizeof(u32),
+ .base.cra_init = crc32_pmull_cra_init,
+ .base.cra_name = "crc32",
+ .base.cra_driver_name = "crc32-arm-ce",
+ .base.cra_priority = 200,
+ .base.cra_blocksize = 1,
+ .base.cra_module = THIS_MODULE,
+};
+
+static int __init crc32_pmull_mod_init(void)
+{
+ if (!(elf_hwcap2 & (HWCAP2_PMULL|HWCAP2_CRC32)))
+ return -ENODEV;
+
+ return crypto_register_shash(&crc32_pmull_alg);
+}
+
+static void __exit crc32_pmull_mod_exit(void)
+{
+ crypto_unregister_shash(&crc32_pmull_alg);
+}
+
+module_init(crc32_pmull_mod_init);
+module_exit(crc32_pmull_mod_exit);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("crc32");
--
2.7.4
^ permalink raw reply related
* [PATCH 4/5] regulator: Add support for TI TWL6032
From: Rosia, Nicolae @ 2016-11-26 20:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201611270236.UFgW5zDA%fengguang.wu@intel.com>
Hi,
On Sun, 2016-11-27 at 02:55 +0800, kbuild test robot wrote:
> Hi Nicolae,
>
> [auto build test ERROR on omap/for-next]
> [also build test ERROR on v4.9-rc6]
> [cannot apply to next-20161125]
> [if your patch is applied to the wrong git tree, please drop us a
> note to help improve the system]
>
> url:????https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-tw
> l-improvements-and-new-regulator-driver/20161127-022201
> base:???https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-
> omap.git for-next
> config: i386-allmodconfig (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
> ????????# save the attached .config to linux build tree
> ????????make ARCH=i386?
>
> All error/warnings (new ones prefixed by >>):
>
> ???In file included from drivers/regulator/twl6032-regulator.c:11:0:
> > > drivers/regulator/twl6032-regulator.c:557:31: error:
> > > 'twl6032_regulator_driver_ids' undeclared here (not in a
> > > function)
>
> ????MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
> ??????????????????????????????????^
> ???include/linux/module.h:213:21: note: in definition of macro
> 'MODULE_DEVICE_TABLE'
> ????extern const typeof(name)
> __mod_##type##__##name##_device_table??\
> ????????????????????????^~~~
> > > include/linux/module.h:213:27: error:
> > > '__mod_platform__twl6032_regulator_driver_ids_device_table'
> > > aliased to undefined symbol 'twl6032_regulator_driver_ids'
>
> ????extern const typeof(name)
> __mod_##type##__##name##_device_table??\
> ??????????????????????????????^
> > > drivers/regulator/twl6032-regulator.c:557:1: note: in expansion
> > > of macro 'MODULE_DEVICE_TABLE'
>
> ????MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
> ????^~~~~~~~~~~~~~~~~~~
>
> vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-
> regulator.c
>
> ???551
> ???552 static const struct of_device_id twl6032_dt_match[] = {
> ???553 { .compatible = "ti,twl6032-regulator" },
> ???554 { /* last entry */ }
> ???555 };
> ???556
> ?> 557 MODULE_DEVICE_TABLE(platform,
> twl6032_regulator_driver_ids);
> ???558
> ???559 static struct platform_driver twl6032_regulator_driver
> = {
> ???560 .driver = {
Thanks, I did not notice this since I was only testing using built-in
module.
I will wait for comments before sending V2, untill then here's an
inline patch with the fix.
Best regards,
Nicolae
^ permalink raw reply
* [PATCH 15/22] arm64/cpuinfo: Make hotplug notifier symmetric
From: Sebastian Andrzej Siewior @ 2016-11-26 23:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161126231350.10321-1-bigeasy@linutronix.de>
From: Anna-Maria Gleixner <anna-maria@linutronix.de>
There is no requirement to keep the sysfs files around until the CPU is
completely dead. Remove them during the DOWN_PREPARE notification. This is
a preparatory patch for converting to the hotplug state machine.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/arm64/kernel/cpuinfo.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index b3d5b3e8fbcb..19aad7041e14 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -272,9 +272,10 @@ static int cpuid_callback(struct notifier_block *nb,
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_ONLINE:
+ case CPU_DOWN_FAILED:
rc = cpuid_add_regs(cpu);
break;
- case CPU_DEAD:
+ case CPU_DOWN_PREPARE:
rc = cpuid_remove_regs(cpu);
break;
}
--
2.10.2
^ permalink raw reply related
* [PATCH 16/22] arm64/cpuinfo: Convert to hotplug state machine
From: Sebastian Andrzej Siewior @ 2016-11-26 23:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161126231350.10321-1-bigeasy@linutronix.de>
From: Anna-Maria Gleixner <anna-maria@linutronix.de>
Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
arch/arm64/kernel/cpuinfo.c | 37 +++++++++----------------------------
1 file changed, 9 insertions(+), 28 deletions(-)
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 19aad7041e14..7b7be71e87bf 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -227,7 +227,7 @@ static struct attribute_group cpuregs_attr_group = {
.name = "identification"
};
-static int cpuid_add_regs(int cpu)
+static int cpuid_cpu_online(unsigned int cpu)
{
int rc;
struct device *dev;
@@ -248,7 +248,7 @@ static int cpuid_add_regs(int cpu)
return rc;
}
-static int cpuid_remove_regs(int cpu)
+static int cpuid_cpu_offline(unsigned int cpu)
{
struct device *dev;
struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
@@ -264,41 +264,22 @@ static int cpuid_remove_regs(int cpu)
return 0;
}
-static int cpuid_callback(struct notifier_block *nb,
- unsigned long action, void *hcpu)
-{
- int rc = 0;
- unsigned long cpu = (unsigned long)hcpu;
-
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
- case CPU_DOWN_FAILED:
- rc = cpuid_add_regs(cpu);
- break;
- case CPU_DOWN_PREPARE:
- rc = cpuid_remove_regs(cpu);
- break;
- }
-
- return notifier_from_errno(rc);
-}
-
static int __init cpuinfo_regs_init(void)
{
- int cpu;
-
- cpu_notifier_register_begin();
+ int cpu, ret;
for_each_possible_cpu(cpu) {
struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
kobject_init(&info->kobj, &cpuregs_kobj_type);
- if (cpu_online(cpu))
- cpuid_add_regs(cpu);
}
- __hotcpu_notifier(cpuid_callback, 0);
- cpu_notifier_register_done();
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/cpuinfo:online",
+ cpuid_cpu_online, cpuid_cpu_offline);
+ if (ret < 0) {
+ pr_err("cpuinfo: failed to register hotplug callbacks.\n");
+ return ret;
+ }
return 0;
}
static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
--
2.10.2
^ permalink raw reply related
* [PATCH 1/2] kbuild: provide include/asm/asm-prototypes.h for ARM
From: Nicolas Pitre @ 2016-11-27 2:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123103640.GC14217@n2100.armlinux.org.uk>
On Wed, 23 Nov 2016, Russell King - ARM Linux wrote:
> On Wed, Nov 23, 2016 at 09:33:32AM +0000, Russell King - ARM Linux wrote:
> > So, I still think the whole approach is wrong - it's added extra
> > fragility that wasn't there with the armksyms.c approach.
>
> Here's what the diffstat and patch looks like when you combine the
> original commit and the three fixes. The LoC delta of 25 lines can
> be accounted for as deleted commentry. So, I think (as I've detailed
> above) that the _technical_ benefit of the approach is very low.
>
> If we want to move the exports into assembly files, I've no problem
> with that, provided we can do it better than this - and by better I
> mean not creating the fragile asm-prototypes.h which divorses the
> prototypes from everything else.
I think we agree on that.
I see that the revert made it to Linus' tree. That's probably the best
outcome for now.
I was working on that better solution I alluded to previously. And it
isn't really complicated either, with much fewer lines of code. But
this can wait for the next merge window.
Nicolas
^ permalink raw reply
* [PATCH 1/2] Documentation: sample averaging for imx6ul_tsc
From: Guy Shapiro @ 2016-11-27 7:44 UTC (permalink / raw)
To: linux-arm-kernel
The i.MX6UL internal touchscreen controller contains an option to
average upon samples. This feature reduces noise from the produced
touch locations.
This patch introduces a new device tree optional property for this
feature. It provides control over the amount of averaged samples per
touch event.
The property was inspired by a similar property on the
"brcm,iproc-touchscreen" binding.
Signed-off-by: Guy Shapiro <guy.shapiro@mobi-wize.com>
---
.../devicetree/bindings/input/touchscreen/imx6ul_tsc.txt | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt b/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt
index 853dff9..a66069f 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt
@@ -17,6 +17,13 @@ Optional properties:
This value depends on the touch screen.
- pre-charge-time: the touch screen need some time to precharge.
This value depends on the touch screen.
+- average-samples: Number of data samples which are averaged for each read.
+ Valid values 0-4
+ 0 = 1 sample
+ 1 = 4 samples
+ 2 = 8 samples
+ 3 = 16 samples
+ 4 = 32 samples
Example:
tsc: tsc at 02040000 {
@@ -32,5 +39,6 @@ Example:
xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
measure-delay-time = <0xfff>;
pre-charge-time = <0xffff>;
+ average-samples = <4>;
status = "okay";
};
--
2.1.4
^ permalink raw reply related
* [PATCH 2/2] input: touchscreen: sample averaging for imx6ul_tsc
From: Guy Shapiro @ 2016-11-27 7:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480232698-23075-1-git-send-email-guy.shapiro@mobi-wize.com>
The i.MX6UL internal touchscreen controller contains an option to
average upon samples. This feature reduces noise from the produced
touch locations.
This patch adds sample averaging support to the imx6ul_tsc device
driver.
Signed-off-by: Guy Shapiro <guy.shapiro@mobi-wize.com>
---
drivers/input/touchscreen/imx6ul_tsc.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c
index 8275267..31724d9 100644
--- a/drivers/input/touchscreen/imx6ul_tsc.c
+++ b/drivers/input/touchscreen/imx6ul_tsc.c
@@ -25,6 +25,7 @@
/* ADC configuration registers field define */
#define ADC_AIEN (0x1 << 7)
#define ADC_CONV_DISABLE 0x1F
+#define ADC_AVGE (0x1 << 5)
#define ADC_CAL (0x1 << 7)
#define ADC_CALF 0x2
#define ADC_12BIT_MODE (0x2 << 2)
@@ -32,6 +33,7 @@
#define ADC_CLK_DIV_8 (0x03 << 5)
#define ADC_SHORT_SAMPLE_MODE (0x0 << 4)
#define ADC_HARDWARE_TRIGGER (0x1 << 13)
+#define ADC_AVGS_SHIFT 14
#define SELECT_CHANNEL_4 0x04
#define SELECT_CHANNEL_1 0x01
#define DISABLE_CONVERSION_INT (0x0 << 7)
@@ -86,6 +88,7 @@ struct imx6ul_tsc {
int measure_delay_time;
int pre_charge_time;
+ int average_samples;
struct completion completion;
};
@@ -107,6 +110,8 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
adc_cfg |= ADC_12BIT_MODE | ADC_IPG_CLK;
adc_cfg |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE;
+ if (tsc->average_samples)
+ adc_cfg |= (tsc->average_samples - 1) << ADC_AVGS_SHIFT;
adc_cfg &= ~ADC_HARDWARE_TRIGGER;
writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
@@ -118,6 +123,8 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
/* start ADC calibration */
adc_gc = readl(tsc->adc_regs + REG_ADC_GC);
adc_gc |= ADC_CAL;
+ if (tsc->average_samples)
+ adc_gc |= ADC_AVGE;
writel(adc_gc, tsc->adc_regs + REG_ADC_GC);
timeout = wait_for_completion_timeout
@@ -450,6 +457,16 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
if (err)
tsc->pre_charge_time = 0xfff;
+ err = of_property_read_u32(np, "average-samples",
+ &tsc->average_samples);
+ if (err)
+ tsc->average_samples = 0;
+ if (tsc->average_samples > 4) {
+ dev_err(&pdev->dev, "average-samples (%u) must be [0-4]\n",
+ tsc->average_samples);
+ return -EINVAL;
+ }
+
err = input_register_device(tsc->input);
if (err) {
dev_err(&pdev->dev,
--
2.1.4
^ permalink raw reply related
* [LINUX RFC v4 0/4] Add stripe support for ZynqMP SoC GQSPI controller
From: Naga Sureshkumar Relli @ 2016-11-27 8:33 UTC (permalink / raw)
To: linux-arm-kernel
This patch series is continuation to previous patches mentioned in below link
http://marc.info/?l=linux-spi&m=145009963109143&w=2
i am re-initiating this series, Could you please help us to get this done?
what is dual parallel mode?
---------------------------
ZynqMP GQSPI controller supports Dual Parallel mode with following functionalities:
1) Supporting two SPI flash memories operating in parallel. 8 I/O lines.
2) Chip selects, data lines and clock are differ to both the flash devices
3) This mode is targeted for faster read/write speed and also doubles the size
4) Commands/data can be transmitted/received from both the devices(mirror),
or only upper or only lower flash memory devices.
5) Data arrangement:
With stripe enabled,
Even bytes i.e. 0, 2, 4,... are transmitted on Lower Data Bus
Odd bytes i.e. 1, 3, 5,.. are transmitted on Upper Data Bus.
i have tested this on top of latest git-hub master.
kindly suggest us the way, so that we can proceed further to add this support.
Naga Sureshkumar Relli (4):
spi: adding support for data stripe feature in core
mtd: add spi_device instance to spi_nor struct
mtd: spi-nor: add stripe support
spi: zynqmp: gqspi: add support for stripe feature
drivers/mtd/devices/m25p80.c | 1 +
drivers/mtd/spi-nor/spi-nor.c | 130 ++++++++++++++++++++++++++++++++---------
drivers/spi/spi-zynqmp-gqspi.c | 26 ++++++++-
drivers/spi/spi.c | 8 +++
include/linux/mtd/spi-nor.h | 3 +
include/linux/spi/spi.h | 11 ++++
6 files changed, 149 insertions(+), 30 deletions(-)
--
2.10.2
^ permalink raw reply
* [LINUX RFC v4 1/4] spi: adding support for data stripe feature in core
From: Naga Sureshkumar Relli @ 2016-11-27 8:33 UTC (permalink / raw)
To: linux-arm-kernel
This patch enables data stripe feature in spi core. This feature is
required to support dual parallel mode of ZynqMP GQSPI controller.
To achieve the same an API SPI_MASTER_DATA_STRIPE is added.
With data stripe enabled,
- even bytes i.e. 0, 2, 4,... are transmitted on lower data bus
- odd bytes i.e. 1, 3, 5,.. are transmitted on upper data bus.
To support data stripe; need to assert both chip selects once.
This is achieved through API SPI_MASTER_BOTH_CS.
Signed-off-by: Naga Sureshkumar Relli <nagasure@xilinx.com>
---
Changes for v4:
- No changes, sending the previous one as is
Change for v3:
- Updated comments for newly added APIs
- Changed patch description for ease of understanding
Changes for v2:
- Added error handling condition for newly added features
---
drivers/spi/spi.c | 8 ++++++++
include/linux/spi/spi.h | 11 +++++++++++
2 files changed, 19 insertions(+)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 5787b72..01980af 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2538,6 +2538,14 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
if (list_empty(&message->transfers))
return -EINVAL;
+ /*
+ * Data stripe option is selected if and only if when
+ * two chips are enabled
+ */
+ if ((master->flags & SPI_MASTER_DATA_STRIPE)
+ && !(master->flags & SPI_MASTER_BOTH_CS))
+ return -EINVAL;
+
/* Half-duplex links include original MicroWire, and ones with
* only one data pin like SPI_3WIRE (switches direction) or where
* either MOSI or MISO is missing. They can also be caused by
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 4b743ac..94a5e6a 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -443,6 +443,17 @@ struct spi_master {
#define SPI_MASTER_MUST_RX BIT(3) /* requires rx */
#define SPI_MASTER_MUST_TX BIT(4) /* requires tx */
+ /* Controller may support data stripe feature when more than one
+ * chips are present.
+ * Setting data stripe will send data in following manner:
+ * -> even bytes i.e. 0, 2, 4,... are transmitted on lower data bus
+ * -> odd bytes i.e. 1, 3, 5,.. are transmitted on upper data bus
+ */
+#define SPI_MASTER_DATA_STRIPE BIT(7) /* support data stripe */
+ /* Controller may support asserting more than one chip select at once.
+ * This flag will enable that feature.
+ */
+#define SPI_MASTER_BOTH_CS BIT(8) /* assert both chip selects */
/*
* on some hardware transfer / message size may be constrained
* the limit may depend on device transfer settings
--
2.10.2
^ permalink raw reply related
* [LINUX RFC v4 2/4] mtd: add spi_device instance to spi_nor struct
From: Naga Sureshkumar Relli @ 2016-11-27 8:33 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds struct spi_device instacne to the spi_nor structure.
Signed-off-by: Naga Sureshkumar Relli <nagasure@xilinx.com>
---
Changes for v4:
- No change
Changes for v3:
- No change
Changes for v2:
- This is new patch, basically splitted on request of Mark Brown
---
drivers/mtd/devices/m25p80.c | 1 +
include/linux/mtd/spi-nor.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 9cf7fcd..58cfb42 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -219,6 +219,7 @@ static int m25p_probe(struct spi_device *spi)
spi_set_drvdata(spi, flash);
flash->spi = spi;
+ nor->spi = spi;
if (spi->mode & SPI_RX_QUAD)
mode = SPI_NOR_QUAD;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index c425c7b..84f3ce5 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -157,6 +157,7 @@ struct spi_nor {
struct mtd_info mtd;
struct mutex lock;
struct device *dev;
+ struct spi_device *spi;
u32 page_size;
u8 addr_width;
u8 erase_opcode;
--
2.10.2
^ permalink raw reply related
* [LINUX RFC v4 3/4] mtd: spi-nor: add stripe support
From: Naga Sureshkumar Relli @ 2016-11-27 8:33 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds stripe support and it is needed for GQSPI parallel
configuration mode by:
- Adding required parameters like stripe and shift to spi_nor
structure.
- Initializing all added parameters in spi_nor_scan()
- Updating read_sr() and read_fsr() for getting status from both
flashes
- Increasing page_size, sector_size, erase_size and toatal flash
size as and when required.
- Dividing address by 2
- Updating spi->master->flags for qspi driver to change CS
Signed-off-by: Naga Sureshkumar Relli <nagasure@xilinx.com>
---
Changes for v4:
- rename isparallel to stripe
Changes for v3:
- No change
Changes for v2:
- Splitted to separate MTD layer changes from SPI core changes
---
drivers/mtd/spi-nor/spi-nor.c | 130 ++++++++++++++++++++++++++++++++----------
include/linux/mtd/spi-nor.h | 2 +
2 files changed, 103 insertions(+), 29 deletions(-)
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d0fc165..4252239 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -22,6 +22,7 @@
#include <linux/of_platform.h>
#include <linux/spi/flash.h>
#include <linux/mtd/spi-nor.h>
+#include <linux/spi/spi.h>
/* Define max times to check status register before we give up. */
@@ -89,15 +90,24 @@ static const struct flash_info *spi_nor_match_id(const char *name);
static int read_sr(struct spi_nor *nor)
{
int ret;
- u8 val;
+ u8 val[2];
- ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1);
- if (ret < 0) {
- pr_err("error %d reading SR\n", (int) ret);
- return ret;
+ if (nor->stripe) {
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val[0], 2);
+ if (ret < 0) {
+ pr_err("error %d reading SR\n", (int) ret);
+ return ret;
+ }
+ val[0] |= val[1];
+ } else {
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val[0], 1);
+ if (ret < 0) {
+ pr_err("error %d reading SR\n", (int) ret);
+ return ret;
+ }
}
- return val;
+ return val[0];
}
/*
@@ -108,15 +118,24 @@ static int read_sr(struct spi_nor *nor)
static int read_fsr(struct spi_nor *nor)
{
int ret;
- u8 val;
+ u8 val[2];
- ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1);
- if (ret < 0) {
- pr_err("error %d reading FSR\n", ret);
- return ret;
+ if (nor->stripe) {
+ ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val[0], 2);
+ if (ret < 0) {
+ pr_err("error %d reading FSR\n", ret);
+ return ret;
+ }
+ val[0] &= val[1];
+ } else {
+ ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val[0], 1);
+ if (ret < 0) {
+ pr_err("error %d reading FSR\n", ret);
+ return ret;
+ }
}
- return val;
+ return val[0];
}
/*
@@ -290,9 +309,16 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
*/
static int erase_chip(struct spi_nor *nor)
{
+ u32 ret;
+
dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10));
- return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0);
+ ret = nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0);
+ if (ret)
+ return ret;
+
+ return ret;
+
}
static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops)
@@ -349,7 +375,7 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
- u32 addr, len;
+ u32 addr, len, offset;
uint32_t rem;
int ret;
@@ -399,9 +425,13 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
/* "sector"-at-a-time erase */
} else {
while (len) {
+
write_enable(nor);
+ offset = addr;
+ if (nor->stripe)
+ offset /= 2;
- ret = spi_nor_erase_sector(nor, addr);
+ ret = spi_nor_erase_sector(nor, offset);
if (ret)
goto erase_err;
@@ -525,6 +555,8 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
bool use_top;
int ret;
+ ofs = ofs >> nor->shift;
+
status_old = read_sr(nor);
if (status_old < 0)
return status_old;
@@ -610,6 +642,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
bool use_top;
int ret;
+ ofs = ofs >> nor->shift;
+
status_old = read_sr(nor);
if (status_old < 0)
return status_old;
@@ -709,6 +743,8 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
if (ret)
return ret;
+ ofs = ofs >> nor->shift;
+
ret = nor->flash_lock(nor, ofs, len);
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
@@ -724,6 +760,8 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
if (ret)
return ret;
+ ofs = ofs >> nor->shift;
+
ret = nor->flash_unlock(nor, ofs, len);
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
@@ -1018,6 +1056,9 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
u8 id[SPI_NOR_MAX_ID_LEN];
const struct flash_info *info;
+ nor->spi->master->flags &= ~(SPI_MASTER_BOTH_CS |
+ SPI_MASTER_DATA_STRIPE);
+
tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
if (tmp < 0) {
dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp);
@@ -1041,6 +1082,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
int ret;
+ u32 offset = from;
dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
@@ -1049,7 +1091,13 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
return ret;
while (len) {
- ret = nor->read(nor, from, len, buf);
+
+ offset = from;
+
+ if (nor->stripe)
+ offset /= 2;
+
+ ret = nor->read(nor, offset, len, buf);
if (ret == 0) {
/* We shouldn't see 0-length reads */
ret = -EIO;
@@ -1161,6 +1209,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
struct spi_nor *nor = mtd_to_spi_nor(mtd);
size_t page_offset, page_remain, i;
ssize_t ret;
+ u32 offset;
dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
@@ -1178,9 +1227,13 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
/* the size of data remaining on the first page */
page_remain = min_t(size_t,
nor->page_size - page_offset, len - i);
+ offset = (to + i);
+
+ if (nor->stripe)
+ offset /= 2;
write_enable(nor);
- ret = nor->write(nor, to + i, page_remain, buf + i);
+ ret = nor->write(nor, (offset), page_remain, buf + i);
if (ret < 0)
goto write_err;
written = ret;
@@ -1302,22 +1355,22 @@ static int spi_nor_check(struct spi_nor *nor)
int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
{
- const struct flash_info *info = NULL;
+ struct flash_info *info = NULL;
struct device *dev = nor->dev;
struct mtd_info *mtd = &nor->mtd;
struct device_node *np = spi_nor_get_flash_node(nor);
- int ret;
- int i;
+ struct device_node *np_spi;
+ int ret, i, xlnx_qspi_mode;
ret = spi_nor_check(nor);
if (ret)
return ret;
if (name)
- info = spi_nor_match_id(name);
+ info = (struct flash_info *)spi_nor_match_id(name);
/* Try to auto-detect if chip name wasn't specified or not found */
if (!info)
- info = spi_nor_read_id(nor);
+ info = (struct flash_info *)spi_nor_read_id(nor);
if (IS_ERR_OR_NULL(info))
return -ENOENT;
@@ -1341,7 +1394,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
*/
dev_warn(dev, "found %s, expected %s\n",
jinfo->name, info->name);
- info = jinfo;
+ info = (struct flash_info *)jinfo;
}
}
@@ -1370,6 +1423,27 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
mtd->size = info->sector_size * info->n_sectors;
mtd->_erase = spi_nor_erase;
mtd->_read = spi_nor_read;
+#ifdef CONFIG_OF
+ np_spi = of_get_next_parent(np);
+
+ if (of_property_read_u32(np_spi, "xlnx,qspi-mode",
+ &xlnx_qspi_mode) < 0) {
+ nor->shift = 0;
+ nor->stripe = 0;
+ } else if (xlnx_qspi_mode == 2) {
+ nor->shift = 1;
+ info->sector_size <<= nor->shift;
+ info->page_size <<= nor->shift;
+ mtd->size <<= nor->shift;
+ nor->stripe = 1;
+ nor->spi->master->flags |= (SPI_MASTER_BOTH_CS |
+ SPI_MASTER_DATA_STRIPE);
+ }
+#else
+ /* Default to single */
+ nor->shift = 0;
+ nor->stripe = 0;
+#endif
/* NOR protection support for STmicro/Micron chips and similar */
if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
@@ -1400,10 +1474,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
/* prefer "small sector" erase if possible */
if (info->flags & SECT_4K) {
nor->erase_opcode = SPINOR_OP_BE_4K;
- mtd->erasesize = 4096;
+ mtd->erasesize = 4096 << nor->shift;
} else if (info->flags & SECT_4K_PMC) {
nor->erase_opcode = SPINOR_OP_BE_4K_PMC;
- mtd->erasesize = 4096;
+ mtd->erasesize = 4096 << nor->shift;
} else
#endif
{
@@ -1508,16 +1582,14 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
dev_info(dev, "%s (%lld Kbytes)\n", info->name,
(long long)mtd->size >> 10);
- dev_dbg(dev,
- "mtd .name = %s, .size = 0x%llx (%lldMiB), "
+ dev_dbg(dev, "mtd .name = %s, .size = 0x%llx (%lldMiB), "
".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20),
mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions);
if (mtd->numeraseregions)
for (i = 0; i < mtd->numeraseregions; i++)
- dev_dbg(dev,
- "mtd.eraseregions[%d] = { .offset = 0x%llx, "
+ dev_dbg(dev, "mtd.eraseregions[%d] = { .offset = 0x%llx, "
".erasesize = 0x%.8x (%uKiB), "
".numblocks = %d }\n",
i, (long long)mtd->eraseregions[i].offset,
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 84f3ce5..673ec68 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -165,6 +165,8 @@ struct spi_nor {
u8 read_dummy;
u8 program_opcode;
enum read_mode flash_read;
+ bool shift;
+ bool stripe;
bool sst_write_second;
u32 flags;
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
--
2.10.2
^ permalink raw reply related
* [LINUX RFC v4 4/4] spi: zynqmp: gqspi: add support for stripe feature
From: Naga Sureshkumar Relli @ 2016-11-27 8:33 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support of dual parallel mode configuration
for Zynq Ultrascale+ MPSoC GQSPI controller driver.
Signed-off-by: Naga Sureshkumar Relli <nagasure@xilinx.com>
---
Changes for v4:
- No changes
Changes for v3:
- No change
Changes for v2:
- No change
---
drivers/spi/spi-zynqmp-gqspi.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 18aeace..dc7cf03 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -153,6 +153,7 @@ enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
* @dma_rx_bytes: Remaining bytes to receive by DMA mode
* @dma_addr: DMA address after mapping the kernel buffer
* @genfifoentry: Used for storing the genfifoentry instruction.
+ * @isinstr: To determine whether the transfer is instruction
* @mode: Defines the mode in which QSPI is operating
*/
struct zynqmp_qspi {
@@ -170,6 +171,7 @@ struct zynqmp_qspi {
u32 dma_rx_bytes;
dma_addr_t dma_addr;
u32 genfifoentry;
+ bool isinstr;
enum mode_type mode;
};
@@ -404,11 +406,24 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
u32 genfifoentry = 0x0, statusreg;
genfifoentry |= GQSPI_GENFIFO_MODE_SPI;
+
+
+ if (qspi->master->flags & SPI_MASTER_BOTH_CS) {
+ zynqmp_gqspi_selectslave(xqspi,
+ GQSPI_SELECT_FLASH_CS_BOTH,
+ GQSPI_SELECT_FLASH_BUS_BOTH);
+ } else {
+ zynqmp_gqspi_selectslave(xqspi,
+ GQSPI_SELECT_FLASH_CS_LOWER,
+ GQSPI_SELECT_FLASH_BUS_LOWER);
+ }
+
genfifoentry |= xqspi->genfifobus;
if (!is_high) {
genfifoentry |= xqspi->genfifocs;
genfifoentry |= GQSPI_GENFIFO_CS_SETUP;
+ xqspi->isinstr = true;
} else {
genfifoentry |= GQSPI_GENFIFO_CS_HOLD;
}
@@ -665,6 +680,7 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
if ((xqspi->bytes_to_receive == 0) && (xqspi->bytes_to_transfer == 0)
&& ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) {
zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK);
+ xqspi->isinstr = false;
spi_finalize_current_transfer(master);
ret = IRQ_HANDLED;
}
@@ -828,6 +844,9 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master,
genfifoentry |= xqspi->genfifocs;
genfifoentry |= xqspi->genfifobus;
+ if ((!xqspi->isinstr) && (master->flags & SPI_MASTER_DATA_STRIPE))
+ genfifoentry |= GQSPI_GENFIFO_STRIPE;
+
zynqmp_qspi_txrxsetup(xqspi, transfer, &genfifoentry);
if (xqspi->mode == GQSPI_MODE_DMA)
@@ -980,6 +999,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
struct zynqmp_qspi *xqspi;
struct resource *res;
struct device *dev = &pdev->dev;
+ u32 num_cs;
master = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
if (!master)
@@ -1040,7 +1060,11 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
goto clk_dis_all;
}
- master->num_chipselect = GQSPI_DEFAULT_NUM_CS;
+ ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
+ if (ret < 0)
+ master->num_chipselect = GQSPI_DEFAULT_NUM_CS;
+ else
+ master->num_chipselect = num_cs;
master->setup = zynqmp_qspi_setup;
master->set_cs = zynqmp_qspi_chipselect;
--
2.10.2
^ permalink raw reply related
* [PATCH v2 2/3] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Icenowy Zheng @ 2016-11-27 9:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161121162421.800-2-icenowy@aosc.xyz>
22.11.2016, 00:26, "Icenowy Zheng" <icenowy@aosc.xyz>:
> Orange Pi Zero is a board that came with the new Allwinner H2+ SoC.
>
> Add a device tree file for it.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes since v2:
> - Use generic pinconf binding instead of legacy allwinner pinctrl binding.
> - removed uart3, which is not accessible on Orange Pi Zero.
> - Removed sun8i-h2plus.dtsi and make Orange Pi Zero dts directly include
> ??sun8i-h3.dtsi.
> - Removed allwinner,sun8i-h3 compatible.
>
> ?arch/arm/boot/dts/Makefile | 1 +
> ?arch/arm/boot/dts/sun8i-h2plus-orangepi-zero.dts | 137 +++++++++++++++++++++++
> ?2 files changed, 138 insertions(+)
> ?create mode 100644 arch/arm/boot/dts/sun8i-h2plus-orangepi-zero.dts
>
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 802a10d..51a1dd7 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -834,6 +834,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
> ?????????sun8i-a33-sinlinx-sina33.dtb \
> ?????????sun8i-a83t-allwinner-h8homlet-v2.dtb \
> ?????????sun8i-a83t-cubietruck-plus.dtb \
> + sun8i-h2plus-orangepi-zero.dtb \
> ?????????sun8i-h3-bananapi-m2-plus.dtb \
> ?????????sun8i-h3-nanopi-neo.dtb \
> ?????????sun8i-h3-orangepi-2.dtb \
> diff --git a/arch/arm/boot/dts/sun8i-h2plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2plus-orangepi-zero.dts
> new file mode 100644
> index 0000000..b428e47
> --- /dev/null
> +++ b/arch/arm/boot/dts/sun8i-h2plus-orangepi-zero.dts
> @@ -0,0 +1,137 @@
> +/*
> + * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Based on sun8i-h3-orangepi-one.dts, which is:
> + * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.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>
> +
> +/ {
> + model = "Xunlong Orange Pi Zero";
> + compatible = "xunlong,orangepi-zero", "allwinner,sun8i-h2plus";
> +
> + aliases {
> + serial0 = &uart0;
> + };
> +
> + chosen {
> + stdout-path = "serial0:115200n8";
> + };
> +
> + leds {
> + compatible = "gpio-leds";
> + pinctrl-names = "default";
> + pinctrl-0 = <&leds_opi0>, <&leds_r_opi0>;
> +
> + pwr_led {
> + label = "orangepi:green:pwr";
> + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
> + default-state = "on";
> + };
> +
> + status_led {
> + label = "orangepi:red:status";
> + gpios = <&pio 0 17 GPIO_ACTIVE_HIGH>;
> + };
> + };
> +};
> +
> +&ehci1 {
> + 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";
> +};
> +
> +&ohci1 {
> + status = "okay";
> +};
> +
> +&pio {
> + leds_opi0: led_pins at 0 {
> + pins = "PA17";
> + function = "gpio_out";
> + };
> +};
> +
> +&r_pio {
> + leds_r_opi0: led_pins at 0 {
> + pins = "PL10";
> + function = "gpio_out";
> + };
> +};
> +
> +&uart0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart0_pins_a>;
> + status = "okay";
> +};
> +
> +&uart1 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart1_pins>;
> + status = "disabled";
> +};
> +
> +&uart2 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&uart2_pins>;
> + status = "disabled";
> +};
> +
> +&usbphy {
> + /* USB VBUS is always on */
> + status = "okay";
> +};
Something more interesting happened.
Xunlong made a add-on board for Orange Pi Zero, which exposes the two USB Controllers exported at expansion bus as USB Type-A connectors.
Also it exposes a analog A/V jack and a microphone.
Should I enable {e,o}hci{2.3} in the device tree?
> --
> 2.10.2
^ permalink raw reply
* [PATCH 1/2] Documentation: sample averaging for imx6ul_tsc
From: Fabio Estevam @ 2016-11-27 12:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480232698-23075-1-git-send-email-guy.shapiro@mobi-wize.com>
On Sun, Nov 27, 2016 at 5:44 AM, Guy Shapiro <guy.shapiro@mobi-wize.com> wrote:
> The i.MX6UL internal touchscreen controller contains an option to
> average upon samples. This feature reduces noise from the produced
> touch locations.
>
> This patch introduces a new device tree optional property for this
> feature. It provides control over the amount of averaged samples per
> touch event.
>
> The property was inspired by a similar property on the
> "brcm,iproc-touchscreen" binding.
>
> Signed-off-by: Guy Shapiro <guy.shapiro@mobi-wize.com>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
^ permalink raw reply
* [PATCH 2/2] input: touchscreen: sample averaging for imx6ul_tsc
From: Fabio Estevam @ 2016-11-27 12:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480232698-23075-2-git-send-email-guy.shapiro@mobi-wize.com>
On Sun, Nov 27, 2016 at 5:44 AM, Guy Shapiro <guy.shapiro@mobi-wize.com> wrote:
> The i.MX6UL internal touchscreen controller contains an option to
> average upon samples. This feature reduces noise from the produced
> touch locations.
>
> This patch adds sample averaging support to the imx6ul_tsc device
> driver.
>
> Signed-off-by: Guy Shapiro <guy.shapiro@mobi-wize.com>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
^ permalink raw reply
* [PATCH v2 1/7] MFD: add bindings for stm32 general purpose timer driver
From: Jonathan Cameron @ 2016-11-27 14:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480000463-9625-2-git-send-email-benjamin.gaignard@st.com>
On 24/11/16 15:14, Benjamin Gaignard wrote:
> Add bindings information for stm32 general purpose timer
>
> version 2:
> - rename stm32-mfd-timer to stm32-gptimer
> - only keep one compatible string
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
> .../bindings/mfd/stm32-general-purpose-timer.txt | 43 ++++++++++++++++++++++
> 1 file changed, 43 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
>
> diff --git a/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt b/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
> new file mode 100644
> index 0000000..2f10e67
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
> @@ -0,0 +1,43 @@
> +STM32 general purpose timer driver
> +
> +Required parameters:
> +- compatible: must be "st,stm32-gptimer"
> +
> +- reg: Physical base address and length of the controller's
> + registers.
> +- clock-names: Set to "clk_int".
> +- clocks: Phandle to the clock used by the timer module.
> + For Clk properties, please refer to ../clock/clock-bindings.txt
> +
> +Optional parameters:
> +- resets: Phandle to the parent reset controller.
> + See ..reset/st,stm32-rcc.txt
> +
> +Optional subnodes:
> +- pwm: See ../pwm/pwm-stm32.txt
> +- iiotimer: See ../iio/timer/stm32-iio-timer.txt
Naming issue here. Can't mention IIO as that's a linux subsystem and all
bindings must be independent of OS.
Perhaps adc-trigger-timer?
> +
> +Example:
> + gptimer1: gptimer1 at 40010000 {
> + compatible = "st,stm32-gptimer";
> + reg = <0x40010000 0x400>;
> + clocks = <&rcc 0 160>;
> + clock-names = "clk_int";
> +
> + pwm1 at 0 {
> + compatible = "st,stm32-pwm";
> + st,pwm-num-chan = <4>;
> + st,breakinput;
> + st,complementary;
> + };
> +
> + iiotimer1 at 0 {
> + compatible = "st,stm32-iio-timer";
Again, avoid the use of iio in here (same issue you had with mfd in the previous
version).
> + interrupts = <27>;
> + st,input-triggers-names = TIM5_TRGO,
Docs for these should be introduced before they are used in an example.
Same for the PWM ones above. Expand the detail fo the example as you add
the other elements.
> + TIM2_TRGO,
> + TIM4_TRGO,
> + TIM3_TRGO;
> + st,output-triggers-names = TIM1_TRGO;
> + };
> + };
>
^ permalink raw reply
* [PATCH v2 3/7] PWM: add pwm-stm32 DT bindings
From: Jonathan Cameron @ 2016-11-27 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480000463-9625-4-git-send-email-benjamin.gaignard@st.com>
On 24/11/16 15:14, Benjamin Gaignard wrote:
> Define bindings for pwm-stm32
>
> version 2:
> - use parameters instead of compatible of handle the hardware configuration
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
> .../devicetree/bindings/pwm/pwm-stm32.txt | 37 ++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/pwm/pwm-stm32.txt
>
> diff --git a/Documentation/devicetree/bindings/pwm/pwm-stm32.txt b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> new file mode 100644
> index 0000000..36263f0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> @@ -0,0 +1,37 @@
> +STMicroelectronics PWM driver bindings for STM32
> +
> +Must be a sub-node of STM32 general purpose timer driver
> +
> +Required parameters:
> +- compatible: Must be "st,stm32-pwm"
> +- pinctrl-names: Set to "default".
> +- pinctrl-0: List of phandles pointing to pin configuration nodes
> + for PWM module.
> + For Pinctrl properties, please refer to [1].
> +
> +Optional parameters:
> +- st,breakinput: Set if the hardware have break input capabilities
> +- st,breakinput-polarity: Set break input polarity. Default is 0
> + The value define the active polarity:
> + - 0 (active LOW)
> + - 1 (active HIGH)
> +- st,pwm-num-chan: Number of available PWM channels. Default is 0.
> +- st,32bits-counter: Set if the hardware have a 32 bits counter
> +- st,complementary: Set if the hardware have complementary output channels
> +
> +[1] Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
> +
> +Example:
> + gptimer1: gptimer1 at 40010000 {
Given the example includes chunks for the other binding, make sure to have
explicit cross references in the document.
> + compatible = "st,stm32-gptimer";
> + reg = <0x40010000 0x400>;
> + clocks = <&rcc 0 160>;
> + clock-names = "clk_int";
> +
> + pwm1 at 0 {
> + compatible = "st,stm32-pwm";
> + st,pwm-num-chan = <4>;
> + st,breakinput;
> + st,complementary;
> + };
> + };
>
^ permalink raw reply
* [PATCH v2 5/7] IIO: add bindings for stm32 IIO timer driver
From: Jonathan Cameron @ 2016-11-27 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480000463-9625-6-git-send-email-benjamin.gaignard@st.com>
On 24/11/16 15:14, Benjamin Gaignard wrote:
> Define bindings for stm32 IIO timer
>
> version 2:
> - only keep one compatible
> - add DT parameters to set lists of the triggers:
> one list describe the triggers created by the device
> another one give the triggers accepted by the device
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
> .../bindings/iio/timer/stm32-iio-timer.txt | 41 ++++++++++++++++++++++
> 1 file changed, 41 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/iio/timer/stm32-iio-timer.txt
>
> diff --git a/Documentation/devicetree/bindings/iio/timer/stm32-iio-timer.txt b/Documentation/devicetree/bindings/iio/timer/stm32-iio-timer.txt
> new file mode 100644
> index 0000000..840b417
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/timer/stm32-iio-timer.txt
> @@ -0,0 +1,41 @@
> +timer IIO trigger bindings for STM32
> +
> +Must be a sub-node of STM32 general purpose timer driver
Add a cross reference...
> +
> +Required parameters:
> +- compatible: must be "st,stm32-iio-timer"
st,stm32-adc-timer or something like that.
> +- interrupts: Interrupt for this device
> + See ../interrupt-controller/st,stm32-exti.txt
> +
> +Optional parameters:
> +- st,input-triggers-names: List of the possible input triggers for
> + the device
> +- st,output-triggers-names: List of the possible output triggers for
> + the device
What are input / output triggers?
> +
> +Possible triggers are defined in include/dt-bindings/iio/timer/st,stm32-iio-timer.h
> +
> +Example:
> + gptimer1: gptimer1 at 40010000 {
> + compatible = "st,stm32-gptimer";
> + reg = <0x40010000 0x400>;
> + clocks = <&rcc 0 160>;
> + clock-names = "clk_int";
> +
> + pwm1 at 0 {
> + compatible = "st,stm32-pwm";
> + st,pwm-num-chan = <4>;
> + st,breakinput;
> + st,complementary;
> + };
> +
> + iiotimer1 at 0 {
> + compatible = "st,stm32-iio-timer";
> + interrupts = <27>;
> + st,input-triggers-names = TIM5_TRGO,
> + TIM2_TRGO,
> + TIM4_TRGO,
> + TIM3_TRGO;
> + st,output-triggers-names = TIM1_TRGO;
> + };
> + };
>
^ permalink raw reply
* [PATCH v2 1/7] MFD: add bindings for stm32 general purpose timer driver
From: Jonathan Cameron @ 2016-11-27 15:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2b751c4a-3038-4220-05d8-d745c51a3691@kernel.org>
On 27/11/16 14:10, Jonathan Cameron wrote:
> On 24/11/16 15:14, Benjamin Gaignard wrote:
>> Add bindings information for stm32 general purpose timer
>>
>> version 2:
>> - rename stm32-mfd-timer to stm32-gptimer
>> - only keep one compatible string
>>
>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>> ---
>> .../bindings/mfd/stm32-general-purpose-timer.txt | 43 ++++++++++++++++++++++
>> 1 file changed, 43 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt b/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
>> new file mode 100644
>> index 0000000..2f10e67
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/stm32-general-purpose-timer.txt
>> @@ -0,0 +1,43 @@
>> +STM32 general purpose timer driver
>> +
>> +Required parameters:
>> +- compatible: must be "st,stm32-gptimer"
>> +
>> +- reg: Physical base address and length of the controller's
>> + registers.
>> +- clock-names: Set to "clk_int".
>> +- clocks: Phandle to the clock used by the timer module.
>> + For Clk properties, please refer to ../clock/clock-bindings.txt
>> +
>> +Optional parameters:
>> +- resets: Phandle to the parent reset controller.
>> + See ..reset/st,stm32-rcc.txt
>> +
>> +Optional subnodes:
>> +- pwm: See ../pwm/pwm-stm32.txt
>> +- iiotimer: See ../iio/timer/stm32-iio-timer.txt
> Naming issue here. Can't mention IIO as that's a linux subsystem and all
> bindings must be independent of OS.
>
> Perhaps adc-trigger-timer?
>> +
>> +Example:
>> + gptimer1: gptimer1 at 40010000 {
>> + compatible = "st,stm32-gptimer";
>> + reg = <0x40010000 0x400>;
>> + clocks = <&rcc 0 160>;
>> + clock-names = "clk_int";
>> +
>> + pwm1 at 0 {
>> + compatible = "st,stm32-pwm";
>> + st,pwm-num-chan = <4>;
>> + st,breakinput;
>> + st,complementary;
>> + };
>> +
>> + iiotimer1 at 0 {
>> + compatible = "st,stm32-iio-timer";
> Again, avoid the use of iio in here (same issue you had with mfd in the previous
> version).
>> + interrupts = <27>;
>> + st,input-triggers-names = TIM5_TRGO,
> Docs for these should be introduced before they are used in an example.
> Same for the PWM ones above. Expand the detail fo the example as you add
> the other elements.
I've just dived into the datasheet for these timers.
http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf
I think you need a binding that describes the capabilities of each of the timers
explicitly. Down to the level of whether there is a repetition counter or not.
Each should exists as a separate entity in device tree.
They then have an existence as timers separate to the description of what they
are used for.
Here the only way we are saying they exist is by their use which doesn't feel
right to me.
So I think you need to move back to what you had in the first place. The key
thing is that ever timer needs describing fully. They are different enough
that for example the datasheet doesn't even try to describe them in one section.
(it has 4 separate chapters covering different sets of these hardware blocks).
The naming isn't really based on index, we are talking different hardware
that the datasheet authors have decided not to give different names to!
If they'd called them
advanced timers
generic timers
basic timers
really basic timers meant for driving the DAC (6 and 7)
We'd all have been quite happy with different compatible strings giving away
what they can do.
What you have here is far too specific to what you are trying to do with them
right now.
These things are separately capable of timing capture (which is I guess where
the IIO device later comes in).
So my expectation is that we end up potentially instantiating:
1) An MFD to handle the shared elements of the timers.
2) Up to 12ish timers each with separate existence as a device in the driver model
and in device tree.
(nasty corner cases here are using timers as perscalers for other timers - I'd be
tempted to leave that for now)
Note that each of these devices has a different register set I think? Any shared
bits are handled via the mfd above (if we even need that MFD which I'm starting
to doubt looking at the datasheet).
3) Up to N pwms again with there own existence in the device model. These don't
do much other than wrap the timer and stick it in output mode.
4) Up to N iio triggers - this is basically using the timer as a periodic interrupt
(though without the interrupt having visibility to the kernel) which fires off
sampling on associated ADCs.
5) Up to N iio capture devices for all channels that support timing capture.
Note there is also hardware encoder capture support in these which should be
correctly handled as well. This comes back to an ancient discussion on the
TI ecap units which have similar capabilities (driver never went anywhere but
I think that was because the author left TI).
Certainly for the IIO devices these should no be bound up into one instance
as you have done here.
Anyhow, I fear that right now this discussion is missing the key ingredient
that the hardware is horrendously variable in it's capabilities and really
is 4-5 different types of hardware that just happen to share a few bits of
their offsets in their register maps.
So after all that I'm almost more confused than I was at the start!
Jonathan
>> + TIM2_TRGO,
>> + TIM4_TRGO,
>> + TIM3_TRGO;
>> + st,output-triggers-names = TIM1_TRGO;
>> + };
>> + };
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" 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 6/7] IIO: add STM32 IIO timer driver
From: Jonathan Cameron @ 2016-11-27 15:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480000463-9625-7-git-send-email-benjamin.gaignard@st.com>
I delved into the datasheet after trying to figure this out, so I think
I now sort of understand your intent, but please do answer the questions
inline.
On 24/11/16 15:14, Benjamin Gaignard wrote:
> Timers IPs can be used to generate triggers for other IPs like
> DAC, ADC or other timers.
> Each trigger may result of timer internals signals like counter enable,
> reset or edge, this configuration could be done through "master_mode"
> device attribute.
>
> A timer device could be triggered by other timers, we use the trigger
> name and is_stm32_iio_timer_trigger() function to distinguish them
> and configure IP input switch.
The presence of an IIO device in here was a suprise.. What is it actually for?
I think this needs some examples of usage to make it clear what the aim is.
I was basically expecting to see a driver instantiating one iio trigger
per timer that can act as a trigger. Those would each have sampling frequency
controls and basica enable / disable.
I'm seeing something much more complex here so additional explanation is
needed.
>
> Timer may also decide on which event (edge, level) they could
> be activated by a trigger, this configuration is done by writing in
> "slave_mode" device attribute.
Really? Sounds like magic numbers in sysfs which is never a good idea.
Please document those attributes / or break them up into elements that
don't require magic numbers.
>
> Since triggers could also be used by DAC or ADC their names are defined
> in include/dt-bindings/iio/timer/st,stm32-iio-timer.h so those IPs will be able
> to configure themselves in valid_trigger function
>
> Trigger have a "sampling_frequency" attribute which allow to configure
> timer sampling frequency without using pwm interface
>
> version 2:
> - keep only one compatible
Hmm. I'm not sure I like this as such. We are actually dealing with lots
of instances of a hardware block with only a small amount of shared
infrastrcuture (which is classic mfd teritory). So to my mind we
should have a separate device for each.
> - use st,input-triggers-names and st,output-triggers-names
> to know which triggers are accepted and/or create by the device
I'm not following why we have this cascade setup?
These are triggers, not devices in the IIO context. We need some detailed
description of why you have it setup like this. This would include the
ABI with examples of how you are using it.
Basically I don't currently understand what you are doing :(
Thanks,
Jonathan
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
> drivers/iio/Kconfig | 2 +-
> drivers/iio/Makefile | 1 +
> drivers/iio/timer/Kconfig | 15 +
> drivers/iio/timer/Makefile | 1 +
> drivers/iio/timer/stm32-iio-timer.c | 448 +++++++++++++++++++++
> drivers/iio/trigger/Kconfig | 1 -
> include/dt-bindings/iio/timer/st,stm32-iio-timer.h | 23 ++
> include/linux/iio/timer/stm32-iio-timers.h | 16 +
> 8 files changed, 505 insertions(+), 2 deletions(-)
> create mode 100644 drivers/iio/timer/Kconfig
> create mode 100644 drivers/iio/timer/Makefile
> create mode 100644 drivers/iio/timer/stm32-iio-timer.c
> create mode 100644 include/dt-bindings/iio/timer/st,stm32-iio-timer.h
> create mode 100644 include/linux/iio/timer/stm32-iio-timers.h
>
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 6743b18..2de2a80 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -90,5 +90,5 @@ source "drivers/iio/potentiometer/Kconfig"
> source "drivers/iio/pressure/Kconfig"
> source "drivers/iio/proximity/Kconfig"
> source "drivers/iio/temperature/Kconfig"
> -
> +source "drivers/iio/timer/Kconfig"
> endif # IIO
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index 87e4c43..b797c08 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -32,4 +32,5 @@ obj-y += potentiometer/
> obj-y += pressure/
> obj-y += proximity/
> obj-y += temperature/
> +obj-y += timer/
> obj-y += trigger/
> diff --git a/drivers/iio/timer/Kconfig b/drivers/iio/timer/Kconfig
> new file mode 100644
> index 0000000..7a73bc6
> --- /dev/null
> +++ b/drivers/iio/timer/Kconfig
> @@ -0,0 +1,15 @@
> +#
> +# Timers drivers
> +
> +menu "Timers"
> +
> +config IIO_STM32_TIMER
> + tristate "stm32 iio timer"
> + depends on ARCH_STM32
> + depends on OF
> + select IIO_TRIGGERED_EVENT
> + select MFD_STM32_GP_TIMER
> + help
> + Select this option to enable stm32 timers hardware IPs
> +
> +endmenu
> diff --git a/drivers/iio/timer/Makefile b/drivers/iio/timer/Makefile
> new file mode 100644
> index 0000000..a360c9f
> --- /dev/null
> +++ b/drivers/iio/timer/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_IIO_STM32_TIMER) += stm32-iio-timer.o
> diff --git a/drivers/iio/timer/stm32-iio-timer.c b/drivers/iio/timer/stm32-iio-timer.c
> new file mode 100644
> index 0000000..35f2687
> --- /dev/null
> +++ b/drivers/iio/timer/stm32-iio-timer.c
> @@ -0,0 +1,448 @@
> +/*
> + * stm32-iio-timer.c
> + *
> + * Copyright (C) STMicroelectronics 2016
> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/iio/timer/stm32-iio-timers.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/triggered_event.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/stm32-gptimer.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#define DRIVER_NAME "stm32-iio-timer"
> +
> +struct stm32_iio_timer_dev {
> + struct device *dev;
> + struct regmap *regmap;
> + struct clk *clk;
> + int irq;
> + bool own_timer;
> + unsigned int sampling_frequency;
> + struct iio_trigger *active_trigger;
> +};
> +
> +static ssize_t _store_frequency(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t len)
> +{
> + struct iio_trigger *trig = to_iio_trigger(dev);
> + struct stm32_iio_timer_dev *stm32 = iio_trigger_get_drvdata(trig);
> + unsigned int freq;
> + int ret;
> +
> + ret = kstrtouint(buf, 10, &freq);
> + if (ret)
> + return ret;
> +
> + stm32->sampling_frequency = freq;
> +
> + return len;
> +}
> +
> +static ssize_t _read_frequency(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct iio_trigger *trig = to_iio_trigger(dev);
> + struct stm32_iio_timer_dev *stm32 = iio_trigger_get_drvdata(trig);
> + unsigned long long freq = stm32->sampling_frequency;
> + u32 psc, arr, cr1;
> +
> + regmap_read(stm32->regmap, TIM_CR1, &cr1);
> + regmap_read(stm32->regmap, TIM_PSC, &psc);
> + regmap_read(stm32->regmap, TIM_ARR, &arr);
> +
> + if (psc && arr && (cr1 & TIM_CR1_CEN)) {
> + freq = (unsigned long long)clk_get_rate(stm32->clk);
> + do_div(freq, psc);
> + do_div(freq, arr);
> + }
> +
> + return sprintf(buf, "%d\n", (unsigned int)freq);
> +}
> +
> +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
> + _read_frequency,
> + _store_frequency);
> +
> +static struct attribute *stm32_trigger_attrs[] = {
> + &iio_dev_attr_sampling_frequency.dev_attr.attr,
> + NULL,
> +};
> +
> +static const struct attribute_group stm32_trigger_attr_group = {
> + .attrs = stm32_trigger_attrs,
> +};
> +
> +static const struct attribute_group *stm32_trigger_attr_groups[] = {
> + &stm32_trigger_attr_group,
> + NULL,
> +};
> +
> +static
> +ssize_t _show_master_mode(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
> + u32 cr2;
> +
> + regmap_read(stm32->regmap, TIM_CR2, &cr2);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", (cr2 >> 4) & 0x7);
> +}
> +
> +static
> +ssize_t _store_master_mode(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t len)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
> + u8 mode;
> + int ret;
> +
> + ret = kstrtou8(buf, 10, &mode);
> + if (ret)
> + return ret;
> +
> + if (mode > 0x7)
> + return -EINVAL;
> +
> + regmap_update_bits(stm32->regmap, TIM_CR2, TIM_CR2_MMS, mode << 4);
> +
> + return len;
> +}
> +
> +static IIO_DEVICE_ATTR(master_mode, S_IRUGO | S_IWUSR,
> + _show_master_mode,
> + _store_master_mode,
> + 0);
> +
> +static
> +ssize_t _show_slave_mode(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
> + u32 smcr;
> +
> + regmap_read(stm32->regmap, TIM_SMCR, &smcr);
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", smcr & 0x3);
> +}
> +
> +static
> +ssize_t _store_slave_mode(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t len)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct stm32_iio_timer_dev *stm32 = iio_priv(indio_dev);
> + u8 mode;
> + int ret;
> +
> + ret = kstrtou8(buf, 10, &mode);
> + if (ret)
> + return ret;
> +
> + if (mode > 0x7)
> + return -EINVAL;
How is something called slave mode going to be fed a number between 0 and 7?
Rule of thumb is no magic numbers in sysfs and right now this is looking
rather cryptic to say the least!
> +
> + regmap_update_bits(stm32->regmap, TIM_SMCR, TIM_SMCR_SMS, mode);
> +
> + return len;
> +}
> +
> +static IIO_DEVICE_ATTR(slave_mode, S_IRUGO | S_IWUSR,
There is an iritating move (in terms of noise it's generating) to use values
directly instead fo these defines. Still if you don't fix it here I'll only
get a patch 'fixing' it soon after...
> + _show_slave_mode,
> + _store_slave_mode,
> + 0);
> +
> +static struct attribute *stm32_timer_attrs[] = {
> + &iio_dev_attr_master_mode.dev_attr.attr,
> + &iio_dev_attr_slave_mode.dev_attr.attr,
New ABI so must be documented under Documentation/ABI/testing/sysfs-bus-iio-*
> + NULL,
> +};
> +
> +static const struct attribute_group stm32_timer_attr_group = {
> + .attrs = stm32_timer_attrs,
> +};
> +
> +static int stm32_timer_start(struct stm32_iio_timer_dev *stm32)
> +{
> + unsigned long long prd, div;
> + int prescaler = 0;
> + u32 max_arr = 0xFFFF, cr1;
> +
> + if (stm32->sampling_frequency == 0)
> + return 0;
> +
> + /* Period and prescaler values depends of clock rate */
> + div = (unsigned long long)clk_get_rate(stm32->clk);
> +
> + do_div(div, stm32->sampling_frequency);
> +
> + prd = div;
> +
> + while (div > max_arr) {
> + prescaler++;
> + div = prd;
> + do_div(div, (prescaler + 1));
> + }
> + prd = div;
> +
> + if (prescaler > MAX_TIM_PSC) {
> + dev_err(stm32->dev, "prescaler exceeds the maximum value\n");
> + return -EINVAL;
> + }
> +
> + /* Check that we own the timer */
> + regmap_read(stm32->regmap, TIM_CR1, &cr1);
> + if ((cr1 & TIM_CR1_CEN) && !stm32->own_timer)
> + return -EBUSY;
> +
> + if (!stm32->own_timer) {
> + stm32->own_timer = true;
> + clk_enable(stm32->clk);
> + }
> +
> + regmap_write(stm32->regmap, TIM_PSC, prescaler);
> + regmap_write(stm32->regmap, TIM_ARR, prd - 1);
> + regmap_update_bits(stm32->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
> +
> + /* Force master mode to update mode */
> + regmap_update_bits(stm32->regmap, TIM_CR2, TIM_CR2_MMS, 0x20);
> +
> + /* Make sure that registers are updated */
> + regmap_update_bits(stm32->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
> +
> + /* Enable interrupt */
> + regmap_write(stm32->regmap, TIM_SR, 0);
> + regmap_update_bits(stm32->regmap, TIM_DIER, TIM_DIER_UIE, TIM_DIER_UIE);
> +
> + /* Enable controller */
> + regmap_update_bits(stm32->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
> +
> + return 0;
> +}
> +
> +static int stm32_timer_stop(struct stm32_iio_timer_dev *stm32)
> +{
> + if (!stm32->own_timer)
> + return 0;
> +
> + /* Stop timer */
> + regmap_update_bits(stm32->regmap, TIM_DIER, TIM_DIER_UIE, 0);
> + regmap_update_bits(stm32->regmap, TIM_CR1, TIM_CR1_CEN, 0);
> + regmap_write(stm32->regmap, TIM_PSC, 0);
> + regmap_write(stm32->regmap, TIM_ARR, 0);
> +
> + clk_disable(stm32->clk);
> +
> + stm32->own_timer = false;
> + stm32->active_trigger = NULL;
> +
> + return 0;
> +}
> +
> +static int stm32_set_trigger_state(struct iio_trigger *trig, bool state)
> +{
> + struct stm32_iio_timer_dev *stm32 = iio_trigger_get_drvdata(trig);
> +
> + stm32->active_trigger = trig;
> +
> + if (state)
> + return stm32_timer_start(stm32);
> + else
> + return stm32_timer_stop(stm32);
> +}
> +
> +static irqreturn_t stm32_timer_irq_handler(int irq, void *private)
> +{
> + struct stm32_iio_timer_dev *stm32 = private;
> + u32 sr;
> +
> + regmap_read(stm32->regmap, TIM_SR, &sr);
> + regmap_write(stm32->regmap, TIM_SR, 0);
> +
> + if ((sr & TIM_SR_UIF) && stm32->active_trigger)
> + iio_trigger_poll(stm32->active_trigger);
This is acting like a trigger cascading off another trigger?
Normally this interrupt handler would be directly associated with the
trigger hardware - in this case the timer.
> +
> + return IRQ_HANDLED;
> +}
> +
> +static const struct iio_trigger_ops timer_trigger_ops = {
> + .owner = THIS_MODULE,
> + .set_trigger_state = stm32_set_trigger_state,
> +};
> +
> +static int stm32_setup_iio_triggers(struct stm32_iio_timer_dev *stm32)
> +{
> + int ret;
> + struct property *p;
> + const char *cur = NULL;
> +
> + p = of_find_property(stm32->dev->of_node,
> + "st,output-triggers-names", NULL);
> +
> + while ((cur = of_prop_next_string(p, cur)) != NULL) {
> + struct iio_trigger *trig;
> +
> + trig = devm_iio_trigger_alloc(stm32->dev, "%s", cur);
> + if (!trig)
> + return -ENOMEM;
> +
> + trig->dev.parent = stm32->dev->parent;
> + trig->ops = &timer_trigger_ops;
> + trig->dev.groups = stm32_trigger_attr_groups;
> + iio_trigger_set_drvdata(trig, stm32);
> +
> + ret = devm_iio_trigger_register(stm32->dev, trig);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * is_stm32_iio_timer_trigger
> + * @trig: trigger to be checked
> + *
> + * return true if the trigger is a valid stm32 iio timer trigger
> + * either return false
> + */
> +bool is_stm32_iio_timer_trigger(struct iio_trigger *trig)
> +{
> + return (trig->ops == &timer_trigger_ops);
> +}
> +EXPORT_SYMBOL(is_stm32_iio_timer_trigger);
> +
> +static int stm32_validate_trigger(struct iio_dev *indio_dev,
> + struct iio_trigger *trig)
> +{
> + struct stm32_iio_timer_dev *dev = iio_priv(indio_dev);
> + int ret;
> +
> + if (!is_stm32_iio_timer_trigger(trig))
> + return -EINVAL;
> +
> + ret = of_property_match_string(dev->dev->of_node,
> + "st,input-triggers-names",
> + trig->name);
> +
> + if (ret < 0)
> + return ret;
> +
> + regmap_update_bits(dev->regmap, TIM_SMCR, TIM_SMCR_TS, ret << 4);
> +
> + return 0;
> +}
> +
> +static const struct iio_info stm32_trigger_info = {
> + .driver_module = THIS_MODULE,
> + .validate_trigger = stm32_validate_trigger,
> + .attrs = &stm32_timer_attr_group,
> +};
> +
> +static struct stm32_iio_timer_dev *stm32_setup_iio_device(struct device *dev)
> +{
> + struct iio_dev *indio_dev;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(struct stm32_iio_timer_dev));
> + if (!indio_dev)
> + return NULL;
This is 'unusual'. Why does a trigger driver need an iio_dev at all?
> +
> + indio_dev->name = dev_name(dev);
> + indio_dev->dev.parent = dev;
> + indio_dev->info = &stm32_trigger_info;
> + indio_dev->modes = INDIO_EVENT_TRIGGERED;
> + indio_dev->num_channels = 0;
> + indio_dev->dev.of_node = dev->of_node;
> +
> + ret = iio_triggered_event_setup(indio_dev,
> + NULL,
> + stm32_timer_irq_handler);
So the iio_dev exists to provide the ability to fire this interrupt from
another trigger? Why do you want to do this?
> + if (ret)
> + return NULL;
> +
> + ret = devm_iio_device_register(dev, indio_dev);
> + if (ret) {
> + iio_triggered_event_cleanup(indio_dev);
> + return NULL;
> + }
> +
> + return iio_priv(indio_dev);
> +}
> +
> +static int stm32_iio_timer_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct stm32_iio_timer_dev *stm32;
> + struct stm32_gptimer_dev *mfd = dev_get_drvdata(pdev->dev.parent);
> + int ret;
> +
> + stm32 = stm32_setup_iio_device(dev);
> + if (!stm32)
> + return -ENOMEM;
> +
> + stm32->dev = dev;
> + stm32->regmap = mfd->regmap;
> + stm32->clk = mfd->clk;
> +
> + stm32->irq = platform_get_irq(pdev, 0);
> + if (stm32->irq < 0)
> + return -EINVAL;
> +
> + ret = devm_request_irq(stm32->dev, stm32->irq,
> + stm32_timer_irq_handler, IRQF_SHARED,
> + "iiotimer_event", stm32);
> + if (ret)
> + return ret;
> +
> + ret = stm32_setup_iio_triggers(stm32);
> + if (ret)
> + return ret;
> +
> + platform_set_drvdata(pdev, stm32);
> +
> + return 0;
> +}
> +
> +static int stm32_iio_timer_remove(struct platform_device *pdev)
> +{
> + struct stm32_iio_timer_dev *stm32 = platform_get_drvdata(pdev);
> +
> + iio_triggered_event_cleanup((struct iio_dev *)stm32);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id stm32_trig_of_match[] = {
> + {
> + .compatible = "st,stm32-iio-timer",
> + },
> +};
> +MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
> +
> +static struct platform_driver stm32_iio_timer_driver = {
> + .probe = stm32_iio_timer_probe,
> + .remove = stm32_iio_timer_remove,
> + .driver = {
> + .name = DRIVER_NAME,
> + .of_match_table = stm32_trig_of_match,
> + },
> +};
> +module_platform_driver(stm32_iio_timer_driver);
> +
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_DESCRIPTION("STMicroelectronics STM32 iio timer driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig
> index 809b2e7..f2af4fe 100644
> --- a/drivers/iio/trigger/Kconfig
> +++ b/drivers/iio/trigger/Kconfig
> @@ -46,5 +46,4 @@ config IIO_SYSFS_TRIGGER
>
> To compile this driver as a module, choose M here: the
> module will be called iio-trig-sysfs.
> -
Clear this out...
> endmenu
> diff --git a/include/dt-bindings/iio/timer/st,stm32-iio-timer.h b/include/dt-bindings/iio/timer/st,stm32-iio-timer.h
> new file mode 100644
> index 0000000..d39bf16
> --- /dev/null
> +++ b/include/dt-bindings/iio/timer/st,stm32-iio-timer.h
> @@ -0,0 +1,23 @@
> +/*
> + * st,stm32-iio-timer.h
> + *
> + * Copyright (C) STMicroelectronics 2016
> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#ifndef _DT_BINDINGS_IIO_TIMER_H_
> +#define _DT_BINDINGS_IIO_TIMER_H_
> +
> +#define TIM1_TRGO "tim1_trgo"
> +#define TIM2_TRGO "tim2_trgo"
> +#define TIM3_TRGO "tim3_trgo"
> +#define TIM4_TRGO "tim4_trgo"
> +#define TIM5_TRGO "tim5_trgo"
> +#define TIM6_TRGO "tim6_trgo"
> +#define TIM7_TRGO "tim7_trgo"
> +#define TIM8_TRGO "tim8_trgo"
> +#define TIM9_TRGO "tim9_trgo"
> +#define TIM12_TRGO "tim12_trgo"
> +
> +#endif
> diff --git a/include/linux/iio/timer/stm32-iio-timers.h b/include/linux/iio/timer/stm32-iio-timers.h
> new file mode 100644
> index 0000000..5d1b86c
> --- /dev/null
> +++ b/include/linux/iio/timer/stm32-iio-timers.h
> @@ -0,0 +1,16 @@
> +/*
> + * stm32-iio-timers.h
> + *
> + * Copyright (C) STMicroelectronics 2016
> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#ifndef _STM32_IIO_TIMERS_H_
> +#define _STM32_IIO_TIMERS_H_
> +
> +#include <dt-bindings/iio/timer/st,stm32-iio-timer.h>
> +
> +bool is_stm32_iio_timer_trigger(struct iio_trigger *trig);
> +
> +#endif
>
^ permalink raw reply
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