1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/conf/landfall-examples/mips-ci20-cpm.cfg Sun May 13 01:34:16 2018 +0200
1.3 @@ -0,0 +1,29 @@
1.4 +# this is a configuration to start 'ex_ci20_cpm'
1.5 +
1.6 +local L4 = require("L4");
1.7 +
1.8 +local l = L4.default_loader;
1.9 +
1.10 +local io_buses =
1.11 + {
1.12 + cpm = l:new_channel();
1.13 + };
1.14 +
1.15 +l:start({
1.16 + caps = {
1.17 + cpm = io_buses.cpm:svr(),
1.18 + icu = L4.Env.icu,
1.19 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
1.20 + },
1.21 + log = { "IO", "y" },
1.22 + l4re_dbg = L4.Dbg.Warn,
1.23 + },
1.24 + "rom/io -vvvv rom/hw_devices.io rom/mips-ci20-cpm.io");
1.25 +
1.26 +l:start({
1.27 + caps = {
1.28 + icu = L4.Env.icu,
1.29 + vbus = io_buses.cpm,
1.30 + },
1.31 + },
1.32 + "rom/ex_ci20_cpm");
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/conf/landfall-examples/mips-ci20-cpm.io Sun May 13 01:34:16 2018 +0200
2.3 @@ -0,0 +1,11 @@
2.4 +-- vi:ft=lua
2.5 +-- configuration file for io
2.6 +
2.7 +local hw = Io.system_bus()
2.8 +
2.9 +local bus = Io.Vi.System_bus
2.10 +{
2.11 + CPM = wrap(hw:match("jz4780-cpm"));
2.12 +}
2.13 +
2.14 +Io.add_vbus("cpm", bus)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/conf/landfall-examples/mips-ci20-cpm.list Sun May 13 01:34:16 2018 +0200
3.3 @@ -0,0 +1,14 @@
3.4 +
3.5 +modaddr 0x1100000
3.6 +
3.7 +entry mips-ci20-cpm-example
3.8 +bootstrap bootstrap -serial
3.9 +kernel fiasco -serial_esc
3.10 +roottask moe rom/mips-ci20-cpm.cfg
3.11 +module mips-ci20-cpm.cfg
3.12 +module mips-ci20-cpm.io
3.13 +module plat-mips-ci20/hw_devices.io
3.14 +module l4re
3.15 +module io
3.16 +module ned
3.17 +module ex_ci20_cpm
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/conf/landfall-examples/mips-ci20-i2c.cfg Sun May 13 01:34:16 2018 +0200
4.3 @@ -0,0 +1,29 @@
4.4 +# this is a configuration to start 'ex_ci20_i2c'
4.5 +
4.6 +local L4 = require("L4");
4.7 +
4.8 +local l = L4.default_loader;
4.9 +
4.10 +local io_buses =
4.11 + {
4.12 + i2c = l:new_channel();
4.13 + };
4.14 +
4.15 +l:start({
4.16 + caps = {
4.17 + i2c = io_buses.i2c:svr(),
4.18 + icu = L4.Env.icu,
4.19 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
4.20 + },
4.21 + log = { "IO", "y" },
4.22 + l4re_dbg = L4.Dbg.Warn,
4.23 + },
4.24 + "rom/io -vvvv rom/hw_devices.io rom/mips-ci20-i2c.io");
4.25 +
4.26 +l:start({
4.27 + caps = {
4.28 + icu = L4.Env.icu,
4.29 + vbus = io_buses.i2c,
4.30 + },
4.31 + },
4.32 + "rom/ex_ci20_i2c");
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/conf/landfall-examples/mips-ci20-i2c.io Sun May 13 01:34:16 2018 +0200
5.3 @@ -0,0 +1,13 @@
5.4 +-- vi:ft=lua
5.5 +-- configuration file for io
5.6 +
5.7 +local hw = Io.system_bus()
5.8 +
5.9 +local bus = Io.Vi.System_bus
5.10 +{
5.11 + CPM = wrap(hw:match("jz4780-cpm"));
5.12 + GPIO = wrap(hw:match("jz4780-gpio"));
5.13 + I2C = wrap(hw:match("jz4780-i2c"));
5.14 +}
5.15 +
5.16 +Io.add_vbus("i2c", bus)
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/conf/landfall-examples/mips-ci20-i2c.list Sun May 13 01:34:16 2018 +0200
6.3 @@ -0,0 +1,14 @@
6.4 +
6.5 +modaddr 0x1100000
6.6 +
6.7 +entry mips-ci20-i2c-example
6.8 +bootstrap bootstrap -serial
6.9 +kernel fiasco -serial_esc
6.10 +roottask moe rom/mips-ci20-i2c.cfg
6.11 +module mips-ci20-i2c.cfg
6.12 +module mips-ci20-i2c.io
6.13 +module plat-mips-ci20/hw_devices.io
6.14 +module l4re
6.15 +module io
6.16 +module ned
6.17 +module ex_ci20_i2c
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/conf/landfall-examples/mips-ci20-led.cfg Sun May 13 01:34:16 2018 +0200
7.3 @@ -0,0 +1,29 @@
7.4 +# this is a configuration to start 'ex_ci20_leds'
7.5 +
7.6 +local L4 = require("L4");
7.7 +
7.8 +local l = L4.default_loader;
7.9 +
7.10 +local io_buses =
7.11 + {
7.12 + gpio = l:new_channel();
7.13 + };
7.14 +
7.15 +l:start({
7.16 + caps = {
7.17 + gpio = io_buses.gpio:svr(),
7.18 + icu = L4.Env.icu,
7.19 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
7.20 + },
7.21 + log = { "IO", "y" },
7.22 + l4re_dbg = L4.Dbg.Warn,
7.23 + },
7.24 + "rom/io -vvvv rom/hw_devices.io rom/mips-ci20-led.io");
7.25 +
7.26 +l:start({
7.27 + caps = {
7.28 + icu = L4.Env.icu,
7.29 + vbus = io_buses.gpio,
7.30 + },
7.31 + },
7.32 + "rom/ex_ci20_leds");
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/conf/landfall-examples/mips-ci20-led.io Sun May 13 01:34:16 2018 +0200
8.3 @@ -0,0 +1,11 @@
8.4 +-- vi:ft=lua
8.5 +-- configuration file for io
8.6 +
8.7 +local hw = Io.system_bus()
8.8 +
8.9 +local bus = Io.Vi.System_bus
8.10 +{
8.11 + GPIO = wrap(hw:match("jz4780-gpio"));
8.12 +}
8.13 +
8.14 +Io.add_vbus("gpio", bus)
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/conf/landfall-examples/mips-ci20-led.list Sun May 13 01:34:16 2018 +0200
9.3 @@ -0,0 +1,14 @@
9.4 +
9.5 +modaddr 0x1100000
9.6 +
9.7 +entry mips-ci20-led-example
9.8 +bootstrap bootstrap -serial
9.9 +kernel fiasco -serial_esc
9.10 +roottask moe rom/mips-ci20-led.cfg
9.11 +module mips-ci20-led.cfg
9.12 +module mips-ci20-led.io
9.13 +module plat-mips-ci20/hw_devices.io
9.14 +module l4re
9.15 +module io
9.16 +module ned
9.17 +module ex_ci20_leds
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/conf/landfall-examples/mips-letux400-fbdrv.cfg Sun May 13 01:34:16 2018 +0200
10.3 @@ -0,0 +1,105 @@
10.4 +-- vim: ft=lua ts=2 et sw=2
10.5 +
10.6 +-- Start the framebuffer driver with supporting devices.
10.7 +-- The target platform is the Letux 400 notebook computer.
10.8 +
10.9 +local L4 = require("L4");
10.10 +
10.11 +local l = L4.default_loader;
10.12 +
10.13 +-- Define general access to peripherals.
10.14 +
10.15 +local io_buses = {
10.16 + cpm = l:new_channel();
10.17 + gpio = l:new_channel();
10.18 + lcd = l:new_channel();
10.19 + pwm = l:new_channel(); -- exposes GPIO, PWM
10.20 + };
10.21 +
10.22 +l:start({
10.23 + caps = {
10.24 + cpm = io_buses.cpm:svr(),
10.25 + gpio = io_buses.gpio:svr(),
10.26 + lcd = io_buses.lcd:svr(),
10.27 + pwm = io_buses.pwm:svr(),
10.28 +
10.29 + icu = L4.Env.icu,
10.30 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
10.31 + },
10.32 + },
10.33 + "rom/io rom/hw_devices.io rom/mips-letux400-fbdrv.io");
10.34 +
10.35 +-- Expose a PWM peripheral as a device.
10.36 +
10.37 +local pwm = l:new_channel();
10.38 +
10.39 +l:startv({
10.40 + caps = {
10.41 + vbus = io_buses.pwm,
10.42 + pwm = pwm:svr(),
10.43 + },
10.44 + },
10.45 + "rom/dev_pwm_jz4730", "0", "250", "299", "47"); -- specifying peripheral number, parameters
10.46 +
10.47 +-- Expose a PWM backlight device.
10.48 +
10.49 +local backlight = l:new_channel(); -- exposes backlight device
10.50 +
10.51 +l:startv({
10.52 + caps = {
10.53 + pwm = pwm,
10.54 + backlight = backlight:svr(),
10.55 + },
10.56 + },
10.57 + "rom/dev_backlight_pwm", "0", "300"); -- specifying limits
10.58 +
10.59 +-- Expose a display device for the Letux.
10.60 +
10.61 +local display = l:new_channel(); -- exposes display device
10.62 +
10.63 +l:start({
10.64 + caps = {
10.65 + backlight = backlight,
10.66 + display = display:svr(),
10.67 + vbus = io_buses.gpio,
10.68 + },
10.69 + },
10.70 + "rom/dev_display_letux400");
10.71 +
10.72 +-- Expose a panel definition for the Letux.
10.73 +
10.74 +local panel = l:new_channel(); -- exposes panel
10.75 +
10.76 +l:start({
10.77 + caps = {
10.78 + panel = panel:svr(),
10.79 + },
10.80 + },
10.81 + "rom/dev_panel_letux400");
10.82 +
10.83 +-- Expose the CPM peripheral.
10.84 +
10.85 +local cpm = l:new_channel();
10.86 +
10.87 +l:start({
10.88 + caps = {
10.89 + vbus = io_buses.cpm,
10.90 + cpm = cpm:svr(),
10.91 + },
10.92 + },
10.93 + "rom/dev_cpm_jz4730");
10.94 +
10.95 +-- Expose a framebuffer device.
10.96 +
10.97 +local fbdrv_fb = l:new_channel();
10.98 +
10.99 +l:start({
10.100 + caps = {
10.101 + vbus = io_buses.lcd,
10.102 + fb = fbdrv_fb:svr(),
10.103 + cpm = cpm,
10.104 + display = display, -- needed by LCD driver
10.105 + panel = panel,
10.106 + },
10.107 + },
10.108 + "rom/fb-drv");
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/conf/landfall-examples/mips-letux400-fbdrv.io Sun May 13 01:34:16 2018 +0200
11.3 @@ -0,0 +1,26 @@
11.4 +-- vim: ft=lua ts=2 et sw=2
11.5 +
11.6 +-- Configuration file for Io.
11.7 +
11.8 +local hw = Io.system_bus()
11.9 +
11.10 +Io.add_vbus("cpm", Io.Vi.System_bus
11.11 +{
11.12 + CPM = wrap(hw:match("jz4730-cpm"));
11.13 +})
11.14 +
11.15 +Io.add_vbus("gpio", Io.Vi.System_bus
11.16 +{
11.17 + GPIO = wrap(hw:match("jz4730-gpio"));
11.18 +})
11.19 +
11.20 +Io.add_vbus("lcd", Io.Vi.System_bus
11.21 +{
11.22 + LCD = wrap(hw:match("jz4740-lcd"));
11.23 +})
11.24 +
11.25 +Io.add_vbus("pwm", Io.Vi.System_bus
11.26 +{
11.27 + GPIO = wrap(hw:match("jz4730-gpio"));
11.28 + PWM = wrap(hw:match("jz4730-pwm"));
11.29 +})
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/conf/landfall-examples/mips-letux400-fbdrv.list Sun May 13 01:34:16 2018 +0200
12.3 @@ -0,0 +1,19 @@
12.4 +
12.5 +modaddr 0x1100000
12.6 +
12.7 +entry mips-letux400-fbdrv-example
12.8 +bootstrap bootstrap -serial
12.9 +kernel fiasco -serial_esc
12.10 +roottask moe rom/mips-letux400-fbdrv.cfg
12.11 +module mips-letux400-fbdrv.cfg
12.12 +module mips-letux400-fbdrv.io
12.13 +module plat-letux400/hw_devices.io
12.14 +module l4re
12.15 +module io
12.16 +module ned
12.17 +module fb-drv
12.18 +module dev_pwm_jz4730
12.19 +module dev_backlight_pwm
12.20 +module dev_display_letux400
12.21 +module dev_panel_letux400
12.22 +module dev_cpm_jz4730
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/conf/landfall-examples/mips-letux400-keypad-demo.cfg Sun May 13 01:34:16 2018 +0200
13.3 @@ -0,0 +1,185 @@
13.4 +-- vim: ft=lua ts=2 et sw=2
13.5 +
13.6 +-- Start Mag to multiplex the framebuffer between several example programs.
13.7 +-- These programs show the keypad status and also allow the backlight to be
13.8 +-- adjusted. The target platform is the Letux 400 notebook computer.
13.9 +
13.10 +local L4 = require("L4");
13.11 +
13.12 +local l = L4.default_loader;
13.13 +
13.14 +-- Define general access to peripherals.
13.15 +
13.16 +local io_buses = {
13.17 + cpm = l:new_channel();
13.18 + gpio = l:new_channel();
13.19 + lcd = l:new_channel();
13.20 + pwm = l:new_channel(); -- exposes GPIO, PWM
13.21 + };
13.22 +
13.23 +l:start({
13.24 + caps = {
13.25 + cpm = io_buses.cpm:svr(),
13.26 + gpio = io_buses.gpio:svr(),
13.27 + lcd = io_buses.lcd:svr(),
13.28 + pwm = io_buses.pwm:svr(),
13.29 +
13.30 + icu = L4.Env.icu,
13.31 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
13.32 + },
13.33 + },
13.34 + "rom/io rom/hw_devices.io rom/mips-letux400-keypad-demo.io");
13.35 +
13.36 +-- Expose a PWM peripheral as a device.
13.37 +
13.38 +local pwm = l:new_channel();
13.39 +
13.40 +l:startv({
13.41 + caps = {
13.42 + vbus = io_buses.pwm,
13.43 + pwm = pwm:svr(),
13.44 + },
13.45 + },
13.46 + "rom/dev_pwm_jz4730", "0", "250", "299", "47"); -- specifying peripheral number, parameters
13.47 +
13.48 +-- Expose a PWM backlight device.
13.49 +
13.50 +local backlight = l:new_channel(); -- exposes backlight device
13.51 +
13.52 +l:startv({
13.53 + caps = {
13.54 + pwm = pwm,
13.55 + backlight = backlight:svr(),
13.56 + },
13.57 + },
13.58 + "rom/dev_backlight_pwm", "0", "300"); -- specifying limits
13.59 +
13.60 +-- Expose a display device for the Letux.
13.61 +
13.62 +local display = l:new_channel(); -- exposes display device
13.63 +
13.64 +l:start({
13.65 + caps = {
13.66 + backlight = backlight,
13.67 + display = display:svr(),
13.68 + vbus = io_buses.gpio,
13.69 + },
13.70 + },
13.71 + "rom/dev_display_letux400");
13.72 +
13.73 +-- Expose a panel definition for the Letux.
13.74 +
13.75 +local panel = l:new_channel(); -- exposes panel
13.76 +
13.77 +l:start({
13.78 + caps = {
13.79 + panel = panel:svr(),
13.80 + },
13.81 + },
13.82 + "rom/dev_panel_letux400");
13.83 +
13.84 +-- Expose the CPM peripheral.
13.85 +
13.86 +local cpm = l:new_channel();
13.87 +
13.88 +l:start({
13.89 + caps = {
13.90 + vbus = io_buses.cpm,
13.91 + cpm = cpm:svr(),
13.92 + },
13.93 + },
13.94 + "rom/dev_cpm_jz4730");
13.95 +
13.96 +-- Expose a framebuffer device.
13.97 +
13.98 +local fbdrv_fb = l:new_channel(); -- exposes framebuffer
13.99 +
13.100 +l:start({
13.101 + caps = {
13.102 + vbus = io_buses.lcd,
13.103 + fb = fbdrv_fb:svr(),
13.104 + cpm = cpm,
13.105 + display = display, -- needed by LCD driver
13.106 + panel = panel,
13.107 + },
13.108 + },
13.109 + "rom/fb-drv");
13.110 +
13.111 +-- Multiplex the framebuffer.
13.112 +
13.113 +local mag_caps = {
13.114 + mag = l:new_channel(),
13.115 + svc = l:new_channel(),
13.116 + };
13.117 +
13.118 +l:start({
13.119 + caps = {
13.120 + vbus = io_buses.gpio, -- needed by input driver
13.121 + fb = fbdrv_fb,
13.122 + mag = mag_caps.mag:svr(),
13.123 + svc = mag_caps.svc:svr(),
13.124 + },
13.125 + },
13.126 + "rom/mag");
13.127 +
13.128 +-- Expose the keypad matrix.
13.129 +
13.130 +local keypad = l:new_channel();
13.131 +
13.132 +l:start({
13.133 + caps = {
13.134 + vbus = io_buses.gpio,
13.135 + keypad = keypad:svr(),
13.136 + },
13.137 + },
13.138 + "rom/dev_keypad_letux400");
13.139 +
13.140 +-- Show the keypad matrix.
13.141 +
13.142 +l:startv({
13.143 + caps = {
13.144 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=400x220+0+0", "barheight=20"),
13.145 + keypad = keypad,
13.146 + },
13.147 + },
13.148 + "rom/ex_keypad_ds_client", "17", "8"); -- specifying keypad matrix dimensions
13.149 +
13.150 +-- Show the physical keypad layout.
13.151 +
13.152 +l:start({
13.153 + caps = {
13.154 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=400x220+400+0", "barheight=20"),
13.155 + keypad = keypad,
13.156 + },
13.157 + },
13.158 + "rom/ex_letux400_keypad_physical");
13.159 +
13.160 +-- Show key event values.
13.161 +
13.162 +l:start({
13.163 + caps = {
13.164 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=400x220+0+240", "barheight=20"),
13.165 + keypad = keypad,
13.166 + },
13.167 + },
13.168 + "rom/ex_letux400_keypad_driver");
13.169 +
13.170 +-- Show key strings.
13.171 +
13.172 +l:startv({
13.173 + caps = {
13.174 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=400x220+400+240", "barheight=20"),
13.175 + keypad = keypad,
13.176 + },
13.177 + },
13.178 + "rom/ex_letux400_keypad_driver", "chars");
13.179 +
13.180 +-- Control the backlight using the keyboard.
13.181 +
13.182 +l:start({
13.183 + caps = {
13.184 + backlight = backlight,
13.185 + keypad = keypad,
13.186 + },
13.187 + },
13.188 + "rom/ex_letux400_backlight");
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/conf/landfall-examples/mips-letux400-keypad-demo.io Sun May 13 01:34:16 2018 +0200
14.3 @@ -0,0 +1,26 @@
14.4 +-- vim: ft=lua ts=2 et sw=2
14.5 +
14.6 +-- Configuration file for Io.
14.7 +
14.8 +local hw = Io.system_bus()
14.9 +
14.10 +Io.add_vbus("cpm", Io.Vi.System_bus
14.11 +{
14.12 + CPM = wrap(hw:match("jz4730-cpm"));
14.13 +})
14.14 +
14.15 +Io.add_vbus("gpio", Io.Vi.System_bus
14.16 +{
14.17 + GPIO = wrap(hw:match("jz4730-gpio"));
14.18 +})
14.19 +
14.20 +Io.add_vbus("lcd", Io.Vi.System_bus
14.21 +{
14.22 + LCD = wrap(hw:match("jz4740-lcd"));
14.23 +})
14.24 +
14.25 +Io.add_vbus("pwm", Io.Vi.System_bus
14.26 +{
14.27 + GPIO = wrap(hw:match("jz4730-gpio"));
14.28 + PWM = wrap(hw:match("jz4730-pwm"));
14.29 +})
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/conf/landfall-examples/mips-letux400-keypad-demo.list Sun May 13 01:34:16 2018 +0200
15.3 @@ -0,0 +1,25 @@
15.4 +
15.5 +modaddr 0x1100000
15.6 +
15.7 +entry mips-letux400-keypad-demo-example
15.8 +bootstrap bootstrap -serial
15.9 +kernel fiasco -serial_esc
15.10 +roottask moe rom/mips-letux400-keypad-demo.cfg
15.11 +module mips-letux400-keypad-demo.cfg
15.12 +module mips-letux400-keypad-demo.io
15.13 +module plat-letux400/hw_devices.io
15.14 +module l4re
15.15 +module io
15.16 +module ned
15.17 +module fb-drv
15.18 +module mag
15.19 +module dev_pwm_jz4730
15.20 +module dev_backlight_pwm
15.21 +module dev_display_letux400
15.22 +module dev_panel_letux400
15.23 +module dev_cpm_jz4730
15.24 +module dev_keypad_letux400
15.25 +module ex_letux400_keypad_driver
15.26 +module ex_keypad_ds_client
15.27 +module ex_letux400_backlight
15.28 +module ex_letux400_keypad_physical
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/conf/landfall-examples/mips-letux400-keypad-driver.cfg Sun May 13 01:34:16 2018 +0200
16.3 @@ -0,0 +1,145 @@
16.4 +-- vim: ft=lua ts=2 et sw=2
16.5 +
16.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
16.7 +-- This example shows the key values produced by the keypad input driver.
16.8 +-- The target platform is the Letux 400 notebook computer.
16.9 +
16.10 +local L4 = require("L4");
16.11 +
16.12 +local l = L4.default_loader;
16.13 +
16.14 +-- Define general access to peripherals.
16.15 +
16.16 +local io_buses = {
16.17 + cpm = l:new_channel();
16.18 + gpio = l:new_channel();
16.19 + lcd = l:new_channel();
16.20 + pwm = l:new_channel(); -- exposes GPIO, PWM
16.21 + };
16.22 +
16.23 +l:start({
16.24 + caps = {
16.25 + cpm = io_buses.cpm:svr(),
16.26 + gpio = io_buses.gpio:svr(),
16.27 + lcd = io_buses.lcd:svr(),
16.28 + pwm = io_buses.pwm:svr(),
16.29 +
16.30 + icu = L4.Env.icu,
16.31 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
16.32 + },
16.33 + },
16.34 + "rom/io rom/hw_devices.io rom/mips-letux400-keypad-driver.io");
16.35 +
16.36 +-- Expose a PWM peripheral as a device.
16.37 +
16.38 +local pwm = l:new_channel();
16.39 +
16.40 +l:startv({
16.41 + caps = {
16.42 + vbus = io_buses.pwm,
16.43 + pwm = pwm:svr(),
16.44 + },
16.45 + },
16.46 + "rom/dev_pwm_jz4730", "0", "250", "299", "47"); -- specifying peripheral number, parameters
16.47 +
16.48 +-- Expose a PWM backlight device.
16.49 +
16.50 +local backlight = l:new_channel(); -- exposes backlight device
16.51 +
16.52 +l:startv({
16.53 + caps = {
16.54 + pwm = pwm,
16.55 + backlight = backlight:svr(),
16.56 + },
16.57 + },
16.58 + "rom/dev_backlight_pwm", "0", "300"); -- specifying limits
16.59 +
16.60 +-- Expose a display device for the Letux.
16.61 +
16.62 +local display = l:new_channel(); -- exposes display device
16.63 +
16.64 +l:start({
16.65 + caps = {
16.66 + backlight = backlight,
16.67 + display = display:svr(),
16.68 + vbus = io_buses.gpio,
16.69 + },
16.70 + },
16.71 + "rom/dev_display_letux400");
16.72 +
16.73 +-- Expose a panel definition for the Letux.
16.74 +
16.75 +local panel = l:new_channel(); -- exposes panel
16.76 +
16.77 +l:start({
16.78 + caps = {
16.79 + panel = panel:svr(),
16.80 + },
16.81 + },
16.82 + "rom/dev_panel_letux400");
16.83 +
16.84 +-- Expose the CPM peripheral.
16.85 +
16.86 +local cpm = l:new_channel();
16.87 +
16.88 +l:start({
16.89 + caps = {
16.90 + vbus = io_buses.cpm,
16.91 + cpm = cpm:svr(),
16.92 + },
16.93 + },
16.94 + "rom/dev_cpm_jz4730");
16.95 +
16.96 +-- Expose a framebuffer device.
16.97 +
16.98 +local fbdrv_fb = l:new_channel();
16.99 +
16.100 +l:start({
16.101 + caps = {
16.102 + vbus = io_buses.lcd,
16.103 + fb = fbdrv_fb:svr(),
16.104 + cpm = cpm,
16.105 + display = display, -- needed by LCD driver
16.106 + panel = panel,
16.107 + },
16.108 + },
16.109 + "rom/fb-drv");
16.110 +
16.111 +-- Multiplex the framebuffer.
16.112 +
16.113 +local mag_caps = {
16.114 + mag = l:new_channel(),
16.115 + svc = l:new_channel(),
16.116 + };
16.117 +
16.118 +l:start({
16.119 + caps = {
16.120 + vbus = io_buses.gpio, -- needed by input driver
16.121 + fb = fbdrv_fb,
16.122 + mag = mag_caps.mag:svr(),
16.123 + svc = mag_caps.svc:svr(),
16.124 + },
16.125 + },
16.126 + "rom/mag");
16.127 +
16.128 +-- Expose the keypad matrix.
16.129 +
16.130 +local keypad = l:new_channel();
16.131 +
16.132 +l:start({
16.133 + caps = {
16.134 + vbus = io_buses.gpio,
16.135 + keypad = keypad:svr(),
16.136 + },
16.137 + },
16.138 + "rom/dev_keypad_letux400");
16.139 +
16.140 +-- Show key event values.
16.141 +
16.142 +l:start({
16.143 + caps = {
16.144 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=800x460+0+0", "barheight=20"),
16.145 + keypad = keypad,
16.146 + },
16.147 + },
16.148 + "rom/ex_letux400_keypad_driver");
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/conf/landfall-examples/mips-letux400-keypad-driver.io Sun May 13 01:34:16 2018 +0200
17.3 @@ -0,0 +1,26 @@
17.4 +-- vim: ft=lua ts=2 et sw=2
17.5 +
17.6 +-- Configuration file for Io.
17.7 +
17.8 +local hw = Io.system_bus()
17.9 +
17.10 +Io.add_vbus("cpm", Io.Vi.System_bus
17.11 +{
17.12 + CPM = wrap(hw:match("jz4730-cpm"));
17.13 +})
17.14 +
17.15 +Io.add_vbus("gpio", Io.Vi.System_bus
17.16 +{
17.17 + GPIO = wrap(hw:match("jz4730-gpio"));
17.18 +})
17.19 +
17.20 +Io.add_vbus("lcd", Io.Vi.System_bus
17.21 +{
17.22 + LCD = wrap(hw:match("jz4740-lcd"));
17.23 +})
17.24 +
17.25 +Io.add_vbus("pwm", Io.Vi.System_bus
17.26 +{
17.27 + GPIO = wrap(hw:match("jz4730-gpio"));
17.28 + PWM = wrap(hw:match("jz4730-pwm"));
17.29 +})
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/conf/landfall-examples/mips-letux400-keypad-driver.list Sun May 13 01:34:16 2018 +0200
18.3 @@ -0,0 +1,22 @@
18.4 +
18.5 +modaddr 0x1100000
18.6 +
18.7 +entry mips-letux400-keypad-driver-example
18.8 +bootstrap bootstrap -serial
18.9 +kernel fiasco -serial_esc
18.10 +roottask moe rom/mips-letux400-keypad-driver.cfg
18.11 +module mips-letux400-keypad-driver.cfg
18.12 +module mips-letux400-keypad-driver.io
18.13 +module plat-letux400/hw_devices.io
18.14 +module l4re
18.15 +module io
18.16 +module ned
18.17 +module fb-drv
18.18 +module mag
18.19 +module dev_pwm_jz4730
18.20 +module dev_backlight_pwm
18.21 +module dev_display_letux400
18.22 +module dev_panel_letux400
18.23 +module dev_cpm_jz4730
18.24 +module dev_keypad_letux400
18.25 +module ex_letux400_keypad_driver
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/conf/landfall-examples/mips-letux400-keypad-ds.cfg Sun May 13 01:34:16 2018 +0200
19.3 @@ -0,0 +1,146 @@
19.4 +-- vim: ft=lua ts=2 et sw=2
19.5 +
19.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
19.7 +-- This example shows the keypad status as read from a memory region exported
19.8 +-- by a separate server that reads the matrix itself.
19.9 +-- The target platform is the Letux 400 notebook computer.
19.10 +
19.11 +local L4 = require("L4");
19.12 +
19.13 +local l = L4.default_loader;
19.14 +
19.15 +-- Define general access to peripherals.
19.16 +
19.17 +local io_buses = {
19.18 + cpm = l:new_channel();
19.19 + gpio = l:new_channel();
19.20 + lcd = l:new_channel();
19.21 + pwm = l:new_channel(); -- exposes GPIO, PWM
19.22 + };
19.23 +
19.24 +l:start({
19.25 + caps = {
19.26 + cpm = io_buses.cpm:svr(),
19.27 + gpio = io_buses.gpio:svr(),
19.28 + lcd = io_buses.lcd:svr(),
19.29 + pwm = io_buses.pwm:svr(),
19.30 +
19.31 + icu = L4.Env.icu,
19.32 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
19.33 + },
19.34 + },
19.35 + "rom/io rom/hw_devices.io rom/mips-letux400-keypad-ds.io");
19.36 +
19.37 +-- Expose a PWM peripheral as a device.
19.38 +
19.39 +local pwm = l:new_channel();
19.40 +
19.41 +l:startv({
19.42 + caps = {
19.43 + vbus = io_buses.pwm,
19.44 + pwm = pwm:svr(),
19.45 + },
19.46 + },
19.47 + "rom/dev_pwm_jz4730", "0", "250", "299", "47"); -- specifying peripheral number, parameters
19.48 +
19.49 +-- Expose a PWM backlight device.
19.50 +
19.51 +local backlight = l:new_channel(); -- exposes backlight device
19.52 +
19.53 +l:startv({
19.54 + caps = {
19.55 + pwm = pwm,
19.56 + backlight = backlight:svr(),
19.57 + },
19.58 + },
19.59 + "rom/dev_backlight_pwm", "0", "300"); -- specifying limits
19.60 +
19.61 +-- Expose a display device for the Letux.
19.62 +
19.63 +local display = l:new_channel(); -- exposes display device
19.64 +
19.65 +l:start({
19.66 + caps = {
19.67 + backlight = backlight,
19.68 + display = display:svr(),
19.69 + vbus = io_buses.gpio,
19.70 + },
19.71 + },
19.72 + "rom/dev_display_letux400");
19.73 +
19.74 +-- Expose a panel definition for the Letux.
19.75 +
19.76 +local panel = l:new_channel(); -- exposes panel
19.77 +
19.78 +l:start({
19.79 + caps = {
19.80 + panel = panel:svr(),
19.81 + },
19.82 + },
19.83 + "rom/dev_panel_letux400");
19.84 +
19.85 +-- Expose the CPM peripheral.
19.86 +
19.87 +local cpm = l:new_channel();
19.88 +
19.89 +l:start({
19.90 + caps = {
19.91 + vbus = io_buses.cpm,
19.92 + cpm = cpm:svr(),
19.93 + },
19.94 + },
19.95 + "rom/dev_cpm_jz4730");
19.96 +
19.97 +-- Expose a framebuffer device.
19.98 +
19.99 +local fbdrv_fb = l:new_channel();
19.100 +
19.101 +l:start({
19.102 + caps = {
19.103 + vbus = io_buses.lcd,
19.104 + fb = fbdrv_fb:svr(),
19.105 + cpm = cpm,
19.106 + display = display, -- needed by LCD driver
19.107 + panel = panel,
19.108 + },
19.109 + },
19.110 + "rom/fb-drv");
19.111 +
19.112 +-- Multiplex the framebuffer.
19.113 +
19.114 +local mag_caps = {
19.115 + mag = l:new_channel(),
19.116 + svc = l:new_channel(),
19.117 + };
19.118 +
19.119 +l:start({
19.120 + caps = {
19.121 + vbus = io_buses.gpio, -- needed by input driver
19.122 + fb = fbdrv_fb,
19.123 + mag = mag_caps.mag:svr(),
19.124 + svc = mag_caps.svc:svr(),
19.125 + },
19.126 + },
19.127 + "rom/mag");
19.128 +
19.129 +-- Expose the keypad matrix.
19.130 +
19.131 +local keypad = l:new_channel();
19.132 +
19.133 +l:start({
19.134 + caps = {
19.135 + vbus = io_buses.gpio,
19.136 + keypad = keypad:svr(),
19.137 + },
19.138 + },
19.139 + "rom/dev_keypad_letux400");
19.140 +
19.141 +-- Show the keypad matrix.
19.142 +
19.143 +l:startv({
19.144 + caps = {
19.145 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=800x460+0+0", "barheight=20"),
19.146 + keypad = keypad,
19.147 + },
19.148 + },
19.149 + "rom/ex_keypad_ds_client", "17", "8"); -- specifying keypad matrix dimensions
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/conf/landfall-examples/mips-letux400-keypad-ds.io Sun May 13 01:34:16 2018 +0200
20.3 @@ -0,0 +1,26 @@
20.4 +-- vim: ft=lua ts=2 et sw=2
20.5 +
20.6 +-- Configuration file for Io.
20.7 +
20.8 +local hw = Io.system_bus()
20.9 +
20.10 +Io.add_vbus("cpm", Io.Vi.System_bus
20.11 +{
20.12 + CPM = wrap(hw:match("jz4730-cpm"));
20.13 +})
20.14 +
20.15 +Io.add_vbus("gpio", Io.Vi.System_bus
20.16 +{
20.17 + GPIO = wrap(hw:match("jz4730-gpio"));
20.18 +})
20.19 +
20.20 +Io.add_vbus("lcd", Io.Vi.System_bus
20.21 +{
20.22 + LCD = wrap(hw:match("jz4740-lcd"));
20.23 +})
20.24 +
20.25 +Io.add_vbus("pwm", Io.Vi.System_bus
20.26 +{
20.27 + GPIO = wrap(hw:match("jz4730-gpio"));
20.28 + PWM = wrap(hw:match("jz4730-pwm"));
20.29 +})
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/conf/landfall-examples/mips-letux400-keypad-ds.list Sun May 13 01:34:16 2018 +0200
21.3 @@ -0,0 +1,22 @@
21.4 +
21.5 +modaddr 0x1100000
21.6 +
21.7 +entry mips-letux400-keypad-ds-example
21.8 +bootstrap bootstrap -serial
21.9 +kernel fiasco -serial_esc
21.10 +roottask moe rom/mips-letux400-keypad-ds.cfg
21.11 +module mips-letux400-keypad-ds.cfg
21.12 +module mips-letux400-keypad-ds.io
21.13 +module plat-letux400/hw_devices.io
21.14 +module l4re
21.15 +module io
21.16 +module ned
21.17 +module fb-drv
21.18 +module mag
21.19 +module dev_pwm_jz4730
21.20 +module dev_backlight_pwm
21.21 +module dev_display_letux400
21.22 +module dev_panel_letux400
21.23 +module dev_cpm_jz4730
21.24 +module dev_keypad_letux400
21.25 +module ex_keypad_ds_client
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/conf/landfall-examples/mips-letux400-keypad.cfg Sun May 13 01:34:16 2018 +0200
22.3 @@ -0,0 +1,133 @@
22.4 +-- vim: ft=lua ts=2 et sw=2
22.5 +
22.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
22.7 +-- This example shows the keypad status as read from the matrix itself.
22.8 +-- The target platform is the Letux 400 notebook computer.
22.9 +
22.10 +local L4 = require("L4");
22.11 +
22.12 +local l = L4.default_loader;
22.13 +
22.14 +-- Define general access to peripherals.
22.15 +
22.16 +local io_buses = {
22.17 + cpm = l:new_channel();
22.18 + gpio = l:new_channel();
22.19 + lcd = l:new_channel();
22.20 + pwm = l:new_channel(); -- exposes GPIO, PWM
22.21 + };
22.22 +
22.23 +l:start({
22.24 + caps = {
22.25 + cpm = io_buses.cpm:svr(),
22.26 + gpio = io_buses.gpio:svr(),
22.27 + lcd = io_buses.lcd:svr(),
22.28 + pwm = io_buses.pwm:svr(),
22.29 +
22.30 + icu = L4.Env.icu,
22.31 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
22.32 + },
22.33 + },
22.34 + "rom/io rom/hw_devices.io rom/mips-letux400-keypad.io");
22.35 +
22.36 +-- Expose a PWM peripheral as a device.
22.37 +
22.38 +local pwm = l:new_channel();
22.39 +
22.40 +l:startv({
22.41 + caps = {
22.42 + vbus = io_buses.pwm,
22.43 + pwm = pwm:svr(),
22.44 + },
22.45 + },
22.46 + "rom/dev_pwm_jz4730", "0", "250", "299", "47"); -- specifying peripheral number, parameters
22.47 +
22.48 +-- Expose a PWM backlight device.
22.49 +
22.50 +local backlight = l:new_channel(); -- exposes backlight device
22.51 +
22.52 +l:startv({
22.53 + caps = {
22.54 + pwm = pwm,
22.55 + backlight = backlight:svr(),
22.56 + },
22.57 + },
22.58 + "rom/dev_backlight_pwm", "0", "300"); -- specifying limits
22.59 +
22.60 +-- Expose a display device for the Letux.
22.61 +
22.62 +local display = l:new_channel(); -- exposes display device
22.63 +
22.64 +l:start({
22.65 + caps = {
22.66 + backlight = backlight,
22.67 + display = display:svr(),
22.68 + vbus = io_buses.gpio,
22.69 + },
22.70 + },
22.71 + "rom/dev_display_letux400");
22.72 +
22.73 +-- Expose a panel definition for the Letux.
22.74 +
22.75 +local panel = l:new_channel(); -- exposes panel
22.76 +
22.77 +l:start({
22.78 + caps = {
22.79 + panel = panel:svr(),
22.80 + },
22.81 + },
22.82 + "rom/dev_panel_letux400");
22.83 +
22.84 +-- Expose the CPM peripheral.
22.85 +
22.86 +local cpm = l:new_channel();
22.87 +
22.88 +l:start({
22.89 + caps = {
22.90 + vbus = io_buses.cpm,
22.91 + cpm = cpm:svr(),
22.92 + },
22.93 + },
22.94 + "rom/dev_cpm_jz4730");
22.95 +
22.96 +-- Expose a framebuffer device.
22.97 +
22.98 +local fbdrv_fb = l:new_channel();
22.99 +
22.100 +l:start({
22.101 + caps = {
22.102 + vbus = io_buses.lcd,
22.103 + fb = fbdrv_fb:svr(),
22.104 + cpm = cpm,
22.105 + display = display, -- needed by LCD driver
22.106 + panel = panel,
22.107 + },
22.108 + },
22.109 + "rom/fb-drv");
22.110 +
22.111 +-- Multiplex the framebuffer.
22.112 +
22.113 +local mag_caps = {
22.114 + mag = l:new_channel(),
22.115 + svc = l:new_channel(),
22.116 + };
22.117 +
22.118 +l:start({
22.119 + caps = {
22.120 + vbus = io_buses.gpio, -- needed by input driver
22.121 + fb = fbdrv_fb,
22.122 + mag = mag_caps.mag:svr(),
22.123 + svc = mag_caps.svc:svr(),
22.124 + },
22.125 + },
22.126 + "rom/mag");
22.127 +
22.128 +-- Show the keypad status.
22.129 +
22.130 +l:start({
22.131 + caps = {
22.132 + vbus = io_buses.gpio,
22.133 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=800x460+0+0", "barheight=20"),
22.134 + },
22.135 + },
22.136 + "rom/ex_letux400_keypad");
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/conf/landfall-examples/mips-letux400-keypad.io Sun May 13 01:34:16 2018 +0200
23.3 @@ -0,0 +1,26 @@
23.4 +-- vim: ft=lua ts=2 et sw=2
23.5 +
23.6 +-- Configuration file for Io.
23.7 +
23.8 +local hw = Io.system_bus()
23.9 +
23.10 +Io.add_vbus("cpm", Io.Vi.System_bus
23.11 +{
23.12 + CPM = wrap(hw:match("jz4730-cpm"));
23.13 +})
23.14 +
23.15 +Io.add_vbus("gpio", Io.Vi.System_bus
23.16 +{
23.17 + GPIO = wrap(hw:match("jz4730-gpio"));
23.18 +})
23.19 +
23.20 +Io.add_vbus("lcd", Io.Vi.System_bus
23.21 +{
23.22 + LCD = wrap(hw:match("jz4740-lcd"));
23.23 +})
23.24 +
23.25 +Io.add_vbus("pwm", Io.Vi.System_bus
23.26 +{
23.27 + GPIO = wrap(hw:match("jz4730-gpio"));
23.28 + PWM = wrap(hw:match("jz4730-pwm"));
23.29 +})
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/conf/landfall-examples/mips-letux400-keypad.list Sun May 13 01:34:16 2018 +0200
24.3 @@ -0,0 +1,38 @@
24.4 +
24.5 +modaddr 0x1100000
24.6 +
24.7 +entry mips-letux400-keypad-example
24.8 +bootstrap bootstrap -serial
24.9 +kernel fiasco -serial_esc
24.10 +roottask moe rom/mips-letux400-keypad.cfg
24.11 +module mips-letux400-keypad.cfg
24.12 +module mips-letux400-keypad.io
24.13 +module plat-letux400/hw_devices.io
24.14 +module l4re
24.15 +module io
24.16 +module ned
24.17 +module fb-drv
24.18 +module mag
24.19 +module dev_pwm_jz4730
24.20 +module dev_backlight_pwm
24.21 +module dev_display_letux400
24.22 +module dev_panel_letux400
24.23 +module dev_cpm_jz4730
24.24 +module ex_letux400_keypad
24.25 +module lib4re-c.so
24.26 +module lib4re-c-util.so
24.27 +module lib4re.so
24.28 +module lib4re-util.so
24.29 +module libc_be_l4refile.so
24.30 +module libc_be_l4re.so
24.31 +module libc_be_socket_noop.so
24.32 +module libc_support_misc.so
24.33 +module libdl.so
24.34 +module libio-io.so
24.35 +module libio-vbus.so
24.36 +module libl4sys.so
24.37 +module libl4util.so
24.38 +module libld-l4.so
24.39 +module libpthread.so
24.40 +module libsupc++.so
24.41 +module libuc_c.so
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/conf/landfall-examples/mips-letux400-lcd-driver.cfg Sun May 13 01:34:16 2018 +0200
25.3 @@ -0,0 +1,102 @@
25.4 +-- vim: ft=lua ts=2 et sw=2
25.5 +
25.6 +-- Test LCD driver code. The target platform is the Letux 400 notebook computer.
25.7 +
25.8 +local L4 = require("L4");
25.9 +
25.10 +local l = L4.default_loader;
25.11 +
25.12 +-- Define general access to peripherals.
25.13 +
25.14 +local io_buses = {
25.15 + cpm = l:new_channel();
25.16 + gpio = l:new_channel();
25.17 + lcd = l:new_channel();
25.18 + pwm = l:new_channel(); -- exposes GPIO, PWM
25.19 + };
25.20 +
25.21 +l:start({
25.22 + caps = {
25.23 + cpm = io_buses.cpm:svr(),
25.24 + gpio = io_buses.gpio:svr(),
25.25 + lcd = io_buses.lcd:svr(),
25.26 + pwm = io_buses.pwm:svr(),
25.27 +
25.28 + icu = L4.Env.icu,
25.29 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
25.30 + },
25.31 + },
25.32 + "rom/io rom/hw_devices.io rom/mips-letux400-lcd-driver.io");
25.33 +
25.34 +-- Expose a PWM peripheral as a device.
25.35 +
25.36 +local pwm = l:new_channel();
25.37 +
25.38 +l:startv({
25.39 + caps = {
25.40 + vbus = io_buses.pwm,
25.41 + pwm = pwm:svr(),
25.42 + },
25.43 + },
25.44 + "rom/dev_pwm_jz4730", "0", "250", "299", "47"); -- specifying peripheral number, parameters
25.45 +
25.46 +-- Expose a PWM backlight device.
25.47 +
25.48 +local backlight = l:new_channel(); -- exposes backlight device
25.49 +
25.50 +l:startv({
25.51 + caps = {
25.52 + pwm = pwm,
25.53 + backlight = backlight:svr(),
25.54 + },
25.55 + },
25.56 + "rom/dev_backlight_pwm", "0", "300"); -- specifying limits
25.57 +
25.58 +-- Expose a display device for the Letux.
25.59 +
25.60 +local display = l:new_channel(); -- exposes display device
25.61 +
25.62 +l:start({
25.63 + caps = {
25.64 + backlight = backlight,
25.65 + display = display:svr(),
25.66 + vbus = io_buses.gpio,
25.67 + },
25.68 + },
25.69 + "rom/dev_display_letux400");
25.70 +
25.71 +-- Expose a panel definition for the Letux.
25.72 +
25.73 +local panel = l:new_channel(); -- exposes panel
25.74 +
25.75 +l:start({
25.76 + caps = {
25.77 + panel = panel:svr(),
25.78 + },
25.79 + },
25.80 + "rom/dev_panel_letux400");
25.81 +
25.82 +-- Expose the CPM peripheral.
25.83 +
25.84 +local cpm = l:new_channel();
25.85 +
25.86 +l:start({
25.87 + caps = {
25.88 + vbus = io_buses.cpm,
25.89 + cpm = cpm:svr(),
25.90 + },
25.91 + },
25.92 + "rom/dev_cpm_jz4730");
25.93 +
25.94 +-- Start and demonstrate the LCD driver.
25.95 +
25.96 +l:start({
25.97 + caps = {
25.98 + icu = L4.Env.icu,
25.99 + vbus = io_buses.lcd,
25.100 + cpm = cpm,
25.101 + display = display, -- needed by LCD driver
25.102 + panel = panel,
25.103 + },
25.104 + },
25.105 + "rom/ex_jz4740_lcd_driver");
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/conf/landfall-examples/mips-letux400-lcd-driver.io Sun May 13 01:34:16 2018 +0200
26.3 @@ -0,0 +1,26 @@
26.4 +-- vim: ft=lua ts=2 et sw=2
26.5 +
26.6 +-- Configuration file for Io.
26.7 +
26.8 +local hw = Io.system_bus()
26.9 +
26.10 +Io.add_vbus("cpm", Io.Vi.System_bus
26.11 +{
26.12 + CPM = wrap(hw:match("jz4730-cpm"));
26.13 +})
26.14 +
26.15 +Io.add_vbus("gpio", Io.Vi.System_bus
26.16 +{
26.17 + GPIO = wrap(hw:match("jz4730-gpio"));
26.18 +})
26.19 +
26.20 +Io.add_vbus("lcd", Io.Vi.System_bus
26.21 +{
26.22 + LCD = wrap(hw:match("jz4740-lcd"));
26.23 +})
26.24 +
26.25 +Io.add_vbus("pwm", Io.Vi.System_bus
26.26 +{
26.27 + GPIO = wrap(hw:match("jz4730-gpio"));
26.28 + PWM = wrap(hw:match("jz4730-pwm"));
26.29 +})
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/conf/landfall-examples/mips-letux400-lcd-driver.list Sun May 13 01:34:16 2018 +0200
27.3 @@ -0,0 +1,19 @@
27.4 +
27.5 +modaddr 0x1100000
27.6 +
27.7 +entry mips-letux400-lcd-driver-example
27.8 +bootstrap bootstrap -serial
27.9 +kernel fiasco -serial_esc
27.10 +roottask moe rom/mips-letux400-lcd-driver.cfg
27.11 +module mips-letux400-lcd-driver.cfg
27.12 +module mips-letux400-lcd-driver.io
27.13 +module plat-letux400/hw_devices.io
27.14 +module l4re
27.15 +module io
27.16 +module ned
27.17 +module dev_pwm_jz4730
27.18 +module dev_backlight_pwm
27.19 +module dev_display_letux400
27.20 +module dev_panel_letux400
27.21 +module dev_cpm_jz4730
27.22 +module ex_jz4740_lcd_driver
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/conf/landfall-examples/mips-letux400-led.cfg Sun May 13 01:34:16 2018 +0200
28.3 @@ -0,0 +1,30 @@
28.4 +-- vim: ft=lua ts=2 et sw=2
28.5 +
28.6 +-- Test the keyboard LEDs via the GPIO peripheral.
28.7 +-- The target platform is the Letux 400 notebook computer.
28.8 +
28.9 +local L4 = require("L4");
28.10 +
28.11 +local l = L4.default_loader;
28.12 +
28.13 +-- Define general access to peripherals.
28.14 +
28.15 +local io_buses = {
28.16 + devices = l:new_channel(); -- exposes GPIO, PWM
28.17 + };
28.18 +
28.19 +l:start({
28.20 + caps = {
28.21 + devices = io_buses.devices:svr(),
28.22 + icu = L4.Env.icu,
28.23 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
28.24 + },
28.25 + },
28.26 + "rom/io rom/hw_devices.io rom/mips-letux400-led.io");
28.27 +
28.28 +l:start({
28.29 + caps = {
28.30 + vbus = io_buses.devices,
28.31 + },
28.32 + },
28.33 + "rom/ex_letux400_leds");
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/conf/landfall-examples/mips-letux400-led.io Sun May 13 01:34:16 2018 +0200
29.3 @@ -0,0 +1,11 @@
29.4 +-- vim: ft=lua ts=2 et sw=2
29.5 +
29.6 +-- Configuration file for Io.
29.7 +
29.8 +local hw = Io.system_bus()
29.9 +
29.10 +Io.add_vbus("devices", Io.Vi.System_bus
29.11 +{
29.12 + GPIO = wrap(hw:match("jz4730-gpio"));
29.13 + PWM = wrap(hw:match("jz4730-pwm"));
29.14 +})
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/conf/landfall-examples/mips-letux400-led.list Sun May 13 01:34:16 2018 +0200
30.3 @@ -0,0 +1,14 @@
30.4 +
30.5 +modaddr 0x1100000
30.6 +
30.7 +entry mips-letux400-led-example
30.8 +bootstrap bootstrap -serial
30.9 +kernel fiasco -serial_esc
30.10 +roottask moe rom/mips-letux400-led.cfg
30.11 +module mips-letux400-led.cfg
30.12 +module mips-letux400-led.io
30.13 +module plat-letux400/hw_devices.io
30.14 +module l4re
30.15 +module io
30.16 +module ned
30.17 +module ex_letux400_leds
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/conf/landfall-examples/mips-letux400-spectrum.cfg Sun May 13 01:34:16 2018 +0200
31.3 @@ -0,0 +1,132 @@
31.4 +-- vim: ft=lua ts=2 et sw=2
31.5 +
31.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
31.7 +-- This example shows an animation showing off a spectrum of colours.
31.8 +-- The target platform is the Letux 400 notebook computer.
31.9 +
31.10 +local L4 = require("L4");
31.11 +
31.12 +local l = L4.default_loader;
31.13 +
31.14 +-- Define general access to peripherals.
31.15 +
31.16 +local io_buses = {
31.17 + cpm = l:new_channel();
31.18 + gpio = l:new_channel();
31.19 + lcd = l:new_channel();
31.20 + pwm = l:new_channel(); -- exposes GPIO, PWM
31.21 + };
31.22 +
31.23 +l:start({
31.24 + caps = {
31.25 + cpm = io_buses.cpm:svr(),
31.26 + gpio = io_buses.gpio:svr(),
31.27 + lcd = io_buses.lcd:svr(),
31.28 + pwm = io_buses.pwm:svr(),
31.29 +
31.30 + icu = L4.Env.icu,
31.31 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
31.32 + },
31.33 + },
31.34 + "rom/io rom/hw_devices.io rom/mips-letux400-spectrum.io");
31.35 +
31.36 +-- Expose a PWM peripheral as a device.
31.37 +
31.38 +local pwm = l:new_channel();
31.39 +
31.40 +l:startv({
31.41 + caps = {
31.42 + vbus = io_buses.pwm,
31.43 + pwm = pwm:svr(),
31.44 + },
31.45 + },
31.46 + "rom/dev_pwm_jz4730", "0", "250", "299", "47"); -- specifying peripheral number, parameters
31.47 +
31.48 +-- Expose a PWM backlight device.
31.49 +
31.50 +local backlight = l:new_channel(); -- exposes backlight device
31.51 +
31.52 +l:startv({
31.53 + caps = {
31.54 + pwm = pwm,
31.55 + backlight = backlight:svr(),
31.56 + },
31.57 + },
31.58 + "rom/dev_backlight_pwm", "0", "300"); -- specifying limits
31.59 +
31.60 +-- Expose a display device for the Letux.
31.61 +
31.62 +local display = l:new_channel(); -- exposes display device
31.63 +
31.64 +l:start({
31.65 + caps = {
31.66 + backlight = backlight,
31.67 + display = display:svr(),
31.68 + vbus = io_buses.gpio,
31.69 + },
31.70 + },
31.71 + "rom/dev_display_letux400");
31.72 +
31.73 +-- Expose a panel definition for the Letux.
31.74 +
31.75 +local panel = l:new_channel(); -- exposes panel
31.76 +
31.77 +l:start({
31.78 + caps = {
31.79 + panel = panel:svr(),
31.80 + },
31.81 + },
31.82 + "rom/dev_panel_letux400");
31.83 +
31.84 +-- Expose the CPM peripheral.
31.85 +
31.86 +local cpm = l:new_channel();
31.87 +
31.88 +l:start({
31.89 + caps = {
31.90 + vbus = io_buses.cpm,
31.91 + cpm = cpm:svr(),
31.92 + },
31.93 + },
31.94 + "rom/dev_cpm_jz4730");
31.95 +
31.96 +-- Expose a framebuffer device.
31.97 +
31.98 +local fbdrv_fb = l:new_channel();
31.99 +
31.100 +l:start({
31.101 + caps = {
31.102 + vbus = io_buses.lcd,
31.103 + fb = fbdrv_fb:svr(),
31.104 + cpm = cpm,
31.105 + display = display, -- needed by LCD driver
31.106 + panel = panel,
31.107 + },
31.108 + },
31.109 + "rom/fb-drv");
31.110 +
31.111 +-- Multiplex the framebuffer.
31.112 +
31.113 +local mag_caps = {
31.114 + mag = l:new_channel(),
31.115 + svc = l:new_channel(),
31.116 + };
31.117 +
31.118 +l:start({
31.119 + caps = {
31.120 + vbus = io_buses.gpio, -- needed by input driver
31.121 + fb = fbdrv_fb,
31.122 + mag = mag_caps.mag:svr(),
31.123 + svc = mag_caps.svc:svr(),
31.124 + },
31.125 + },
31.126 + "rom/mag");
31.127 +
31.128 +-- Show the spectrum example.
31.129 +
31.130 +l:start({
31.131 + caps = {
31.132 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=800x460", "barheight=20"),
31.133 + },
31.134 + },
31.135 + "rom/ex_fb_spectrum_cc");
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/conf/landfall-examples/mips-letux400-spectrum.io Sun May 13 01:34:16 2018 +0200
32.3 @@ -0,0 +1,26 @@
32.4 +-- vim: ft=lua ts=2 et sw=2
32.5 +
32.6 +-- Configuration file for Io.
32.7 +
32.8 +local hw = Io.system_bus()
32.9 +
32.10 +Io.add_vbus("cpm", Io.Vi.System_bus
32.11 +{
32.12 + CPM = wrap(hw:match("jz4730-cpm"));
32.13 +})
32.14 +
32.15 +Io.add_vbus("gpio", Io.Vi.System_bus
32.16 +{
32.17 + GPIO = wrap(hw:match("jz4730-gpio"));
32.18 +})
32.19 +
32.20 +Io.add_vbus("lcd", Io.Vi.System_bus
32.21 +{
32.22 + LCD = wrap(hw:match("jz4740-lcd"));
32.23 +})
32.24 +
32.25 +Io.add_vbus("pwm", Io.Vi.System_bus
32.26 +{
32.27 + GPIO = wrap(hw:match("jz4730-gpio"));
32.28 + PWM = wrap(hw:match("jz4730-pwm"));
32.29 +})
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/conf/landfall-examples/mips-letux400-spectrum.list Sun May 13 01:34:16 2018 +0200
33.3 @@ -0,0 +1,21 @@
33.4 +
33.5 +modaddr 0x1100000
33.6 +
33.7 +entry mips-letux400-spectrum-example
33.8 +bootstrap bootstrap -serial
33.9 +kernel fiasco -serial_esc
33.10 +roottask moe rom/mips-letux400-spectrum.cfg
33.11 +module mips-letux400-spectrum.cfg
33.12 +module mips-letux400-spectrum.io
33.13 +module plat-letux400/hw_devices.io
33.14 +module l4re
33.15 +module io
33.16 +module ned
33.17 +module fb-drv
33.18 +module mag
33.19 +module dev_pwm_jz4730
33.20 +module dev_backlight_pwm
33.21 +module dev_display_letux400
33.22 +module dev_panel_letux400
33.23 +module dev_cpm_jz4730
33.24 +module ex_fb_spectrum_cc
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/conf/landfall-examples/mips-qi_lb60-fbdrv.cfg Sun May 13 01:34:16 2018 +0200
34.3 @@ -0,0 +1,103 @@
34.4 +-- vim: ft=lua ts=2 et sw=2
34.5 +
34.6 +-- Start the framebuffer driver with supporting devices.
34.7 +-- The target platform is the Ben NanoNote.
34.8 +
34.9 +local L4 = require("L4");
34.10 +
34.11 +local l = L4.default_loader;
34.12 +
34.13 +-- Define general access to peripherals.
34.14 +
34.15 +local io_buses = {
34.16 + cpm = l:new_channel();
34.17 + gpio = l:new_channel();
34.18 + lcd = l:new_channel();
34.19 + };
34.20 +
34.21 +l:start({
34.22 + caps = {
34.23 + cpm = io_buses.cpm:svr(),
34.24 + gpio = io_buses.gpio:svr(),
34.25 + lcd = io_buses.lcd:svr(),
34.26 +
34.27 + icu = L4.Env.icu,
34.28 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
34.29 + },
34.30 + },
34.31 + "rom/io rom/hw_devices.io rom/mips-qi_lb60-fbdrv.io");
34.32 +
34.33 +-- Expose a SPI peripheral as a device.
34.34 +
34.35 +local spi = l:new_channel();
34.36 +
34.37 +l:startv({
34.38 + caps = {
34.39 + vbus = io_buses.gpio,
34.40 + spi = spi:svr(),
34.41 + },
34.42 + },
34.43 + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details
34.44 +
34.45 +-- Expose a SPI backlight device for the Ben.
34.46 +
34.47 +local backlight = l:new_channel(); -- exposes backlight device
34.48 +
34.49 +l:start({
34.50 + caps = {
34.51 + spi = spi,
34.52 + backlight = backlight:svr(),
34.53 + },
34.54 + },
34.55 + "rom/dev_backlight_spi_qi_lb60");
34.56 +
34.57 +-- Expose a display device for the Ben.
34.58 +
34.59 +local display = l:new_channel(); -- exposes display device
34.60 +
34.61 +l:start({
34.62 + caps = {
34.63 + backlight = backlight,
34.64 + display = display:svr(),
34.65 + vbus = io_buses.gpio,
34.66 + },
34.67 + },
34.68 + "rom/dev_display_qi_lb60");
34.69 +
34.70 +-- Expose a panel definition for the Ben.
34.71 +
34.72 +local panel = l:new_channel(); -- exposes panel
34.73 +
34.74 +l:start({
34.75 + caps = {
34.76 + panel = panel:svr(),
34.77 + },
34.78 + },
34.79 + "rom/dev_panel_qi_lb60");
34.80 +
34.81 +-- Expose the CPM peripheral.
34.82 +
34.83 +local cpm = l:new_channel();
34.84 +
34.85 +l:start({
34.86 + caps = {
34.87 + vbus = io_buses.cpm,
34.88 + cpm = cpm:svr(),
34.89 + },
34.90 + },
34.91 + "rom/dev_cpm_jz4740");
34.92 +
34.93 +-- Expose a framebuffer device.
34.94 +
34.95 +local fbdrv_fb = l:new_channel();
34.96 +
34.97 +l:start({
34.98 + caps = {
34.99 + vbus = io_buses.lcd,
34.100 + fb = fbdrv_fb:svr(),
34.101 + cpm = cpm,
34.102 + display = display, -- needed by LCD driver
34.103 + panel = panel,
34.104 + },
34.105 + },
34.106 + "rom/fb-drv");
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/conf/landfall-examples/mips-qi_lb60-fbdrv.io Sun May 13 01:34:16 2018 +0200
35.3 @@ -0,0 +1,20 @@
35.4 +-- vim: ft=lua ts=2 et sw=2
35.5 +
35.6 +-- Configuration file for Io.
35.7 +
35.8 +local hw = Io.system_bus()
35.9 +
35.10 +Io.add_vbus("cpm", Io.Vi.System_bus
35.11 +{
35.12 + CPM = wrap(hw:match("jz4740-cpm"));
35.13 +})
35.14 +
35.15 +Io.add_vbus("gpio", Io.Vi.System_bus
35.16 +{
35.17 + GPIO = wrap(hw:match("jz4740-gpio"));
35.18 +})
35.19 +
35.20 +Io.add_vbus("lcd", Io.Vi.System_bus
35.21 +{
35.22 + LCD = wrap(hw:match("jz4740-lcd"));
35.23 +})
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/conf/landfall-examples/mips-qi_lb60-fbdrv.list Sun May 13 01:34:16 2018 +0200
36.3 @@ -0,0 +1,19 @@
36.4 +
36.5 +modaddr 0x1100000
36.6 +
36.7 +entry mips-qi_lb60-fbdrv-example
36.8 +bootstrap bootstrap -serial
36.9 +kernel fiasco -serial_esc
36.10 +roottask moe rom/mips-qi_lb60-fbdrv.cfg
36.11 +module mips-qi_lb60-fbdrv.cfg
36.12 +module mips-qi_lb60-fbdrv.io
36.13 +module plat-qi_lb60/hw_devices.io
36.14 +module l4re
36.15 +module io
36.16 +module ned
36.17 +module fb-drv
36.18 +module dev_spi_jz4740
36.19 +module dev_backlight_spi_qi_lb60
36.20 +module dev_display_qi_lb60
36.21 +module dev_panel_qi_lb60
36.22 +module dev_cpm_jz4740
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-demo.cfg Sun May 13 01:34:16 2018 +0200
37.3 @@ -0,0 +1,183 @@
37.4 +-- vim: ft=lua ts=2 et sw=2
37.5 +
37.6 +-- Start Mag to multiplex the framebuffer between several example programs.
37.7 +-- These programs show the keypad status and also allow the backlight to be
37.8 +-- adjusted. The target platform is the Ben NanoNote.
37.9 +
37.10 +local L4 = require("L4");
37.11 +
37.12 +local l = L4.default_loader;
37.13 +
37.14 +-- Define general access to peripherals.
37.15 +
37.16 +local io_buses = {
37.17 + cpm = l:new_channel();
37.18 + gpio = l:new_channel();
37.19 + lcd = l:new_channel();
37.20 + };
37.21 +
37.22 +l:start({
37.23 + caps = {
37.24 + cpm = io_buses.cpm:svr(),
37.25 + gpio = io_buses.gpio:svr(),
37.26 + lcd = io_buses.lcd:svr(),
37.27 +
37.28 + icu = L4.Env.icu,
37.29 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
37.30 + },
37.31 + },
37.32 + "rom/io rom/hw_devices.io rom/mips-qi_lb60-keypad-demo.io");
37.33 +
37.34 +-- Expose a SPI peripheral as a device.
37.35 +
37.36 +local spi = l:new_channel();
37.37 +
37.38 +l:startv({
37.39 + caps = {
37.40 + vbus = io_buses.gpio,
37.41 + spi = spi:svr(),
37.42 + },
37.43 + },
37.44 + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details
37.45 +
37.46 +-- Expose a SPI backlight device for the Ben.
37.47 +
37.48 +local backlight = l:new_channel(); -- exposes backlight device
37.49 +
37.50 +l:start({
37.51 + caps = {
37.52 + spi = spi,
37.53 + backlight = backlight:svr(),
37.54 + },
37.55 + },
37.56 + "rom/dev_backlight_spi_qi_lb60");
37.57 +
37.58 +-- Expose a display device for the Ben.
37.59 +
37.60 +local display = l:new_channel(); -- exposes display device
37.61 +
37.62 +l:start({
37.63 + caps = {
37.64 + backlight = backlight,
37.65 + display = display:svr(),
37.66 + vbus = io_buses.gpio,
37.67 + },
37.68 + },
37.69 + "rom/dev_display_qi_lb60");
37.70 +
37.71 +-- Expose a panel definition for the Ben.
37.72 +
37.73 +local panel = l:new_channel(); -- exposes panel
37.74 +
37.75 +l:start({
37.76 + caps = {
37.77 + panel = panel:svr(),
37.78 + },
37.79 + },
37.80 + "rom/dev_panel_qi_lb60");
37.81 +
37.82 +-- Expose the CPM peripheral.
37.83 +
37.84 +local cpm = l:new_channel();
37.85 +
37.86 +l:start({
37.87 + caps = {
37.88 + vbus = io_buses.cpm,
37.89 + cpm = cpm:svr(),
37.90 + },
37.91 + },
37.92 + "rom/dev_cpm_jz4740");
37.93 +
37.94 +-- Expose a framebuffer device.
37.95 +
37.96 +local fbdrv_fb = l:new_channel();
37.97 +
37.98 +l:start({
37.99 + caps = {
37.100 + vbus = io_buses.lcd,
37.101 + fb = fbdrv_fb:svr(),
37.102 + cpm = cpm,
37.103 + display = display, -- needed by LCD driver
37.104 + panel = panel,
37.105 + },
37.106 + },
37.107 + "rom/fb-drv");
37.108 +
37.109 +-- Multiplex the framebuffer.
37.110 +
37.111 +local mag_caps = {
37.112 + mag = l:new_channel(),
37.113 + svc = l:new_channel(),
37.114 + };
37.115 +
37.116 +l:start({
37.117 + caps = {
37.118 + vbus = io_buses.gpio, -- needed by input driver
37.119 + fb = fbdrv_fb,
37.120 + mag = mag_caps.mag:svr(),
37.121 + svc = mag_caps.svc:svr(),
37.122 + },
37.123 + },
37.124 + "rom/mag");
37.125 +
37.126 +-- Expose the keypad matrix.
37.127 +
37.128 +local keypad = l:new_channel();
37.129 +
37.130 +l:start({
37.131 + caps = {
37.132 + vbus = io_buses.gpio,
37.133 + keypad = keypad:svr(),
37.134 + },
37.135 + },
37.136 + "rom/dev_keypad_qi_lb60");
37.137 +
37.138 +-- Show the keypad matrix.
37.139 +
37.140 +l:startv({
37.141 + caps = {
37.142 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=160x110+0+0", "barheight=10"),
37.143 + keypad = keypad,
37.144 + },
37.145 + },
37.146 + "rom/ex_keypad_ds_client", "8", "8"); -- specifying keypad matrix dimensions
37.147 +
37.148 +-- Show the physical keypad layout.
37.149 +
37.150 +l:start({
37.151 + caps = {
37.152 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=160x110+160+0", "barheight=10"),
37.153 + keypad = keypad,
37.154 + },
37.155 + },
37.156 + "rom/ex_qi_lb60_keypad_physical");
37.157 +
37.158 +-- Show key event values.
37.159 +
37.160 +l:start({
37.161 + caps = {
37.162 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=160x110+0+120", "barheight=10"),
37.163 + keypad = keypad,
37.164 + },
37.165 + },
37.166 + "rom/ex_qi_lb60_keypad_driver");
37.167 +
37.168 +-- Show key strings.
37.169 +
37.170 +l:startv({
37.171 + caps = {
37.172 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=160x110+160+120", "barheight=10"),
37.173 + keypad = keypad,
37.174 + },
37.175 + },
37.176 + "rom/ex_qi_lb60_keypad_driver", "chars");
37.177 +
37.178 +-- Control the backlight using the keyboard.
37.179 +
37.180 +l:start({
37.181 + caps = {
37.182 + backlight = backlight,
37.183 + keypad = keypad,
37.184 + },
37.185 + },
37.186 + "rom/ex_qi_lb60_backlight");
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-demo.io Sun May 13 01:34:16 2018 +0200
38.3 @@ -0,0 +1,20 @@
38.4 +-- vim: ft=lua ts=2 et sw=2
38.5 +
38.6 +-- Configuration file for Io.
38.7 +
38.8 +local hw = Io.system_bus()
38.9 +
38.10 +Io.add_vbus("cpm", Io.Vi.System_bus
38.11 +{
38.12 + CPM = wrap(hw:match("jz4740-cpm"));
38.13 +})
38.14 +
38.15 +Io.add_vbus("gpio", Io.Vi.System_bus
38.16 +{
38.17 + GPIO = wrap(hw:match("jz4740-gpio"));
38.18 +})
38.19 +
38.20 +Io.add_vbus("lcd", Io.Vi.System_bus
38.21 +{
38.22 + LCD = wrap(hw:match("jz4740-lcd"));
38.23 +})
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-demo.list Sun May 13 01:34:16 2018 +0200
39.3 @@ -0,0 +1,25 @@
39.4 +
39.5 +modaddr 0x1100000
39.6 +
39.7 +entry mips-qi_lb60-keypad-demo-example
39.8 +bootstrap bootstrap -serial
39.9 +kernel fiasco -serial_esc
39.10 +roottask moe rom/mips-qi_lb60-keypad-demo.cfg
39.11 +module mips-qi_lb60-keypad-demo.cfg
39.12 +module mips-qi_lb60-keypad-demo.io
39.13 +module plat-qi_lb60/hw_devices.io
39.14 +module l4re
39.15 +module io
39.16 +module ned
39.17 +module fb-drv
39.18 +module mag
39.19 +module dev_spi_jz4740
39.20 +module dev_backlight_spi_qi_lb60
39.21 +module dev_display_qi_lb60
39.22 +module dev_panel_qi_lb60
39.23 +module dev_cpm_jz4740
39.24 +module dev_keypad_qi_lb60
39.25 +module ex_qi_lb60_keypad_driver
39.26 +module ex_keypad_ds_client
39.27 +module ex_qi_lb60_keypad_physical
39.28 +module ex_qi_lb60_backlight
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-driver.cfg Sun May 13 01:34:16 2018 +0200
40.3 @@ -0,0 +1,143 @@
40.4 +-- vim: ft=lua ts=2 et sw=2
40.5 +
40.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
40.7 +-- This example shows the key values produced by the keypad input driver.
40.8 +-- The target platform is the Ben NanoNote.
40.9 +
40.10 +local L4 = require("L4");
40.11 +
40.12 +local l = L4.default_loader;
40.13 +
40.14 +-- Define general access to peripherals.
40.15 +
40.16 +local io_buses = {
40.17 + cpm = l:new_channel();
40.18 + gpio = l:new_channel();
40.19 + lcd = l:new_channel();
40.20 + };
40.21 +
40.22 +l:start({
40.23 + caps = {
40.24 + cpm = io_buses.cpm:svr(),
40.25 + gpio = io_buses.gpio:svr(),
40.26 + lcd = io_buses.lcd:svr(),
40.27 +
40.28 + icu = L4.Env.icu,
40.29 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
40.30 + },
40.31 + },
40.32 + "rom/io rom/hw_devices.io rom/mips-qi_lb60-keypad-driver.io");
40.33 +
40.34 +-- Expose a SPI peripheral as a device.
40.35 +
40.36 +local spi = l:new_channel();
40.37 +
40.38 +l:startv({
40.39 + caps = {
40.40 + vbus = io_buses.gpio,
40.41 + spi = spi:svr(),
40.42 + },
40.43 + },
40.44 + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details
40.45 +
40.46 +-- Expose a SPI backlight device for the Ben.
40.47 +
40.48 +local backlight = l:new_channel(); -- exposes backlight device
40.49 +
40.50 +l:start({
40.51 + caps = {
40.52 + spi = spi,
40.53 + backlight = backlight:svr(),
40.54 + },
40.55 + },
40.56 + "rom/dev_backlight_spi_qi_lb60");
40.57 +
40.58 +-- Expose a display device for the Ben.
40.59 +
40.60 +local display = l:new_channel(); -- exposes display device
40.61 +
40.62 +l:start({
40.63 + caps = {
40.64 + backlight = backlight,
40.65 + display = display:svr(),
40.66 + vbus = io_buses.gpio,
40.67 + },
40.68 + },
40.69 + "rom/dev_display_qi_lb60");
40.70 +
40.71 +-- Expose a panel definition for the Ben.
40.72 +
40.73 +local panel = l:new_channel(); -- exposes panel
40.74 +
40.75 +l:start({
40.76 + caps = {
40.77 + panel = panel:svr(),
40.78 + },
40.79 + },
40.80 + "rom/dev_panel_qi_lb60");
40.81 +
40.82 +-- Expose the CPM peripheral.
40.83 +
40.84 +local cpm = l:new_channel();
40.85 +
40.86 +l:start({
40.87 + caps = {
40.88 + vbus = io_buses.cpm,
40.89 + cpm = cpm:svr(),
40.90 + },
40.91 + },
40.92 + "rom/dev_cpm_jz4740");
40.93 +
40.94 +-- Expose a framebuffer device.
40.95 +
40.96 +local fbdrv_fb = l:new_channel();
40.97 +
40.98 +l:start({
40.99 + caps = {
40.100 + vbus = io_buses.lcd,
40.101 + fb = fbdrv_fb:svr(),
40.102 + cpm = cpm,
40.103 + display = display, -- needed by LCD driver
40.104 + panel = panel,
40.105 + },
40.106 + },
40.107 + "rom/fb-drv");
40.108 +
40.109 +-- Multiplex the framebuffer.
40.110 +
40.111 +local mag_caps = {
40.112 + mag = l:new_channel(),
40.113 + svc = l:new_channel(),
40.114 + };
40.115 +
40.116 +l:start({
40.117 + caps = {
40.118 + vbus = io_buses.gpio, -- needed by input driver
40.119 + fb = fbdrv_fb,
40.120 + mag = mag_caps.mag:svr(),
40.121 + svc = mag_caps.svc:svr(),
40.122 + },
40.123 + },
40.124 + "rom/mag");
40.125 +
40.126 +-- Expose the keypad matrix.
40.127 +
40.128 +local keypad = l:new_channel();
40.129 +
40.130 +l:start({
40.131 + caps = {
40.132 + vbus = io_buses.gpio,
40.133 + keypad = keypad:svr(),
40.134 + },
40.135 + },
40.136 + "rom/dev_keypad_qi_lb60");
40.137 +
40.138 +-- Show key event values.
40.139 +
40.140 +l:startv({
40.141 + caps = {
40.142 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=320x230+0+0", "barheight=10"),
40.143 + keypad = keypad,
40.144 + },
40.145 + },
40.146 + "rom/ex_qi_lb60_keypad_driver");
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-driver.io Sun May 13 01:34:16 2018 +0200
41.3 @@ -0,0 +1,20 @@
41.4 +-- vim: ft=lua ts=2 et sw=2
41.5 +
41.6 +-- Configuration file for Io.
41.7 +
41.8 +local hw = Io.system_bus()
41.9 +
41.10 +Io.add_vbus("cpm", Io.Vi.System_bus
41.11 +{
41.12 + CPM = wrap(hw:match("jz4740-cpm"));
41.13 +})
41.14 +
41.15 +Io.add_vbus("gpio", Io.Vi.System_bus
41.16 +{
41.17 + GPIO = wrap(hw:match("jz4740-gpio"));
41.18 +})
41.19 +
41.20 +Io.add_vbus("lcd", Io.Vi.System_bus
41.21 +{
41.22 + LCD = wrap(hw:match("jz4740-lcd"));
41.23 +})
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-driver.list Sun May 13 01:34:16 2018 +0200
42.3 @@ -0,0 +1,22 @@
42.4 +
42.5 +modaddr 0x1100000
42.6 +
42.7 +entry mips-qi_lb60-keypad-driver-example
42.8 +bootstrap bootstrap -serial
42.9 +kernel fiasco -serial_esc
42.10 +roottask moe rom/mips-qi_lb60-keypad-driver.cfg
42.11 +module mips-qi_lb60-keypad-driver.cfg
42.12 +module mips-qi_lb60-keypad-driver.io
42.13 +module plat-qi_lb60/hw_devices.io
42.14 +module l4re
42.15 +module io
42.16 +module ned
42.17 +module fb-drv
42.18 +module mag
42.19 +module dev_spi_jz4740
42.20 +module dev_backlight_spi_qi_lb60
42.21 +module dev_display_qi_lb60
42.22 +module dev_panel_qi_lb60
42.23 +module dev_cpm_jz4740
42.24 +module dev_keypad_qi_lb60
42.25 +module ex_qi_lb60_keypad_driver
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-ds.cfg Sun May 13 01:34:16 2018 +0200
43.3 @@ -0,0 +1,144 @@
43.4 +-- vim: ft=lua ts=2 et sw=2
43.5 +
43.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
43.7 +-- This example shows the keypad status as read from a memory region exported
43.8 +-- by a separate server that reads the matrix itself.
43.9 +-- The target platform is the Ben NanoNote.
43.10 +
43.11 +local L4 = require("L4");
43.12 +
43.13 +local l = L4.default_loader;
43.14 +
43.15 +-- Define general access to peripherals.
43.16 +
43.17 +local io_buses = {
43.18 + cpm = l:new_channel();
43.19 + gpio = l:new_channel();
43.20 + lcd = l:new_channel();
43.21 + };
43.22 +
43.23 +l:start({
43.24 + caps = {
43.25 + cpm = io_buses.cpm:svr(),
43.26 + gpio = io_buses.gpio:svr(),
43.27 + lcd = io_buses.lcd:svr(),
43.28 +
43.29 + icu = L4.Env.icu,
43.30 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
43.31 + },
43.32 + },
43.33 + "rom/io rom/hw_devices.io rom/mips-qi_lb60-keypad-ds.io");
43.34 +
43.35 +-- Expose a SPI peripheral as a device.
43.36 +
43.37 +local spi = l:new_channel();
43.38 +
43.39 +l:startv({
43.40 + caps = {
43.41 + vbus = io_buses.gpio,
43.42 + spi = spi:svr(),
43.43 + },
43.44 + },
43.45 + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details
43.46 +
43.47 +-- Expose a SPI backlight device for the Ben.
43.48 +
43.49 +local backlight = l:new_channel(); -- exposes backlight device
43.50 +
43.51 +l:start({
43.52 + caps = {
43.53 + spi = spi,
43.54 + backlight = backlight:svr(),
43.55 + },
43.56 + },
43.57 + "rom/dev_backlight_spi_qi_lb60");
43.58 +
43.59 +-- Expose a display device for the Ben.
43.60 +
43.61 +local display = l:new_channel(); -- exposes display device
43.62 +
43.63 +l:start({
43.64 + caps = {
43.65 + backlight = backlight,
43.66 + display = display:svr(),
43.67 + vbus = io_buses.gpio,
43.68 + },
43.69 + },
43.70 + "rom/dev_display_qi_lb60");
43.71 +
43.72 +-- Expose a panel definition for the Ben.
43.73 +
43.74 +local panel = l:new_channel(); -- exposes panel
43.75 +
43.76 +l:start({
43.77 + caps = {
43.78 + panel = panel:svr(),
43.79 + },
43.80 + },
43.81 + "rom/dev_panel_qi_lb60");
43.82 +
43.83 +-- Expose the CPM peripheral.
43.84 +
43.85 +local cpm = l:new_channel();
43.86 +
43.87 +l:start({
43.88 + caps = {
43.89 + vbus = io_buses.cpm,
43.90 + cpm = cpm:svr(),
43.91 + },
43.92 + },
43.93 + "rom/dev_cpm_jz4740");
43.94 +
43.95 +-- Expose a framebuffer device.
43.96 +
43.97 +local fbdrv_fb = l:new_channel();
43.98 +
43.99 +l:start({
43.100 + caps = {
43.101 + vbus = io_buses.lcd,
43.102 + fb = fbdrv_fb:svr(),
43.103 + cpm = cpm,
43.104 + display = display, -- needed by LCD driver
43.105 + panel = panel,
43.106 + },
43.107 + },
43.108 + "rom/fb-drv");
43.109 +
43.110 +-- Multiplex the framebuffer.
43.111 +
43.112 +local mag_caps = {
43.113 + mag = l:new_channel(),
43.114 + svc = l:new_channel(),
43.115 + };
43.116 +
43.117 +l:start({
43.118 + caps = {
43.119 + vbus = io_buses.gpio, -- needed by input driver
43.120 + fb = fbdrv_fb,
43.121 + mag = mag_caps.mag:svr(),
43.122 + svc = mag_caps.svc:svr(),
43.123 + },
43.124 + },
43.125 + "rom/mag");
43.126 +
43.127 +-- Expose the keypad matrix.
43.128 +
43.129 +local keypad = l:new_channel();
43.130 +
43.131 +l:start({
43.132 + caps = {
43.133 + vbus = io_buses.gpio,
43.134 + keypad = keypad:svr(),
43.135 + },
43.136 + },
43.137 + "rom/dev_keypad_qi_lb60");
43.138 +
43.139 +-- Show the keypad matrix.
43.140 +
43.141 +l:startv({
43.142 + caps = {
43.143 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=320x230+0+0", "barheight=10"),
43.144 + keypad = keypad,
43.145 + },
43.146 + },
43.147 + "rom/ex_keypad_ds_client", "8", "8"); -- specifying keypad matrix dimensions
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-ds.io Sun May 13 01:34:16 2018 +0200
44.3 @@ -0,0 +1,20 @@
44.4 +-- vim: ft=lua ts=2 et sw=2
44.5 +
44.6 +-- Configuration file for Io.
44.7 +
44.8 +local hw = Io.system_bus()
44.9 +
44.10 +Io.add_vbus("cpm", Io.Vi.System_bus
44.11 +{
44.12 + CPM = wrap(hw:match("jz4740-cpm"));
44.13 +})
44.14 +
44.15 +Io.add_vbus("gpio", Io.Vi.System_bus
44.16 +{
44.17 + GPIO = wrap(hw:match("jz4740-gpio"));
44.18 +})
44.19 +
44.20 +Io.add_vbus("lcd", Io.Vi.System_bus
44.21 +{
44.22 + LCD = wrap(hw:match("jz4740-lcd"));
44.23 +})
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad-ds.list Sun May 13 01:34:16 2018 +0200
45.3 @@ -0,0 +1,22 @@
45.4 +
45.5 +modaddr 0x1100000
45.6 +
45.7 +entry mips-qi_lb60-keypad-ds-example
45.8 +bootstrap bootstrap -serial
45.9 +kernel fiasco -serial_esc
45.10 +roottask moe rom/mips-qi_lb60-keypad-ds.cfg
45.11 +module mips-qi_lb60-keypad-ds.cfg
45.12 +module mips-qi_lb60-keypad-ds.io
45.13 +module plat-qi_lb60/hw_devices.io
45.14 +module l4re
45.15 +module io
45.16 +module ned
45.17 +module fb-drv
45.18 +module mag
45.19 +module dev_spi_jz4740
45.20 +module dev_backlight_spi_qi_lb60
45.21 +module dev_display_qi_lb60
45.22 +module dev_panel_qi_lb60
45.23 +module dev_cpm_jz4740
45.24 +module dev_keypad_qi_lb60
45.25 +module ex_keypad_ds_client
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad.cfg Sun May 13 01:34:16 2018 +0200
46.3 @@ -0,0 +1,131 @@
46.4 +-- vim: ft=lua ts=2 et sw=2
46.5 +
46.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
46.7 +-- This example shows the keypad status as read from the matrix itself.
46.8 +-- The target platform is the Ben NanoNote.
46.9 +
46.10 +local L4 = require("L4");
46.11 +
46.12 +local l = L4.default_loader;
46.13 +
46.14 +-- Define general access to peripherals.
46.15 +
46.16 +local io_buses = {
46.17 + cpm = l:new_channel();
46.18 + gpio = l:new_channel();
46.19 + lcd = l:new_channel();
46.20 + };
46.21 +
46.22 +l:start({
46.23 + caps = {
46.24 + cpm = io_buses.cpm:svr(),
46.25 + gpio = io_buses.gpio:svr(),
46.26 + lcd = io_buses.lcd:svr(),
46.27 +
46.28 + icu = L4.Env.icu,
46.29 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
46.30 + },
46.31 + },
46.32 + "rom/io rom/hw_devices.io rom/mips-qi_lb60-keypad.io");
46.33 +
46.34 +-- Expose a SPI peripheral as a device.
46.35 +
46.36 +local spi = l:new_channel();
46.37 +
46.38 +l:startv({
46.39 + caps = {
46.40 + vbus = io_buses.gpio,
46.41 + spi = spi:svr(),
46.42 + },
46.43 + },
46.44 + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details
46.45 +
46.46 +-- Expose a SPI backlight device for the Ben.
46.47 +
46.48 +local backlight = l:new_channel(); -- exposes backlight device
46.49 +
46.50 +l:start({
46.51 + caps = {
46.52 + spi = spi,
46.53 + backlight = backlight:svr(),
46.54 + },
46.55 + },
46.56 + "rom/dev_backlight_spi_qi_lb60");
46.57 +
46.58 +-- Expose a display device for the Ben.
46.59 +
46.60 +local display = l:new_channel(); -- exposes display device
46.61 +
46.62 +l:start({
46.63 + caps = {
46.64 + backlight = backlight,
46.65 + display = display:svr(),
46.66 + vbus = io_buses.gpio,
46.67 + },
46.68 + },
46.69 + "rom/dev_display_qi_lb60");
46.70 +
46.71 +-- Expose a panel definition for the Ben.
46.72 +
46.73 +local panel = l:new_channel(); -- exposes panel
46.74 +
46.75 +l:start({
46.76 + caps = {
46.77 + panel = panel:svr(),
46.78 + },
46.79 + },
46.80 + "rom/dev_panel_qi_lb60");
46.81 +
46.82 +-- Expose the CPM peripheral.
46.83 +
46.84 +local cpm = l:new_channel();
46.85 +
46.86 +l:start({
46.87 + caps = {
46.88 + vbus = io_buses.cpm,
46.89 + cpm = cpm:svr(),
46.90 + },
46.91 + },
46.92 + "rom/dev_cpm_jz4740");
46.93 +
46.94 +-- Expose a framebuffer device.
46.95 +
46.96 +local fbdrv_fb = l:new_channel();
46.97 +
46.98 +l:start({
46.99 + caps = {
46.100 + vbus = io_buses.lcd,
46.101 + fb = fbdrv_fb:svr(),
46.102 + cpm = cpm,
46.103 + display = display, -- needed by LCD driver
46.104 + panel = panel,
46.105 + },
46.106 + },
46.107 + "rom/fb-drv");
46.108 +
46.109 +-- Multiplex the framebuffer.
46.110 +
46.111 +local mag_caps = {
46.112 + mag = l:new_channel(),
46.113 + svc = l:new_channel(),
46.114 + };
46.115 +
46.116 +l:start({
46.117 + caps = {
46.118 + vbus = io_buses.gpio, -- needed by input driver
46.119 + fb = fbdrv_fb,
46.120 + mag = mag_caps.mag:svr(),
46.121 + svc = mag_caps.svc:svr(),
46.122 + },
46.123 + },
46.124 + "rom/mag");
46.125 +
46.126 +-- Show the keypad status.
46.127 +
46.128 +l:start({
46.129 + caps = {
46.130 + vbus = io_buses.gpio,
46.131 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=320x230+0+0", "barheight=10"),
46.132 + },
46.133 + },
46.134 + "rom/ex_qi_lb60_keypad");
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad.io Sun May 13 01:34:16 2018 +0200
47.3 @@ -0,0 +1,20 @@
47.4 +-- vim: ft=lua ts=2 et sw=2
47.5 +
47.6 +-- Configuration file for Io.
47.7 +
47.8 +local hw = Io.system_bus()
47.9 +
47.10 +Io.add_vbus("cpm", Io.Vi.System_bus
47.11 +{
47.12 + CPM = wrap(hw:match("jz4740-cpm"));
47.13 +})
47.14 +
47.15 +Io.add_vbus("gpio", Io.Vi.System_bus
47.16 +{
47.17 + GPIO = wrap(hw:match("jz4740-gpio"));
47.18 +})
47.19 +
47.20 +Io.add_vbus("lcd", Io.Vi.System_bus
47.21 +{
47.22 + LCD = wrap(hw:match("jz4740-lcd"));
47.23 +})
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/conf/landfall-examples/mips-qi_lb60-keypad.list Sun May 13 01:34:16 2018 +0200
48.3 @@ -0,0 +1,21 @@
48.4 +
48.5 +modaddr 0x1100000
48.6 +
48.7 +entry mips-qi_lb60-keypad-example
48.8 +bootstrap bootstrap -serial
48.9 +kernel fiasco -serial_esc
48.10 +roottask moe rom/mips-qi_lb60-keypad.cfg
48.11 +module mips-qi_lb60-keypad.cfg
48.12 +module mips-qi_lb60-keypad.io
48.13 +module plat-qi_lb60/hw_devices.io
48.14 +module l4re
48.15 +module io
48.16 +module ned
48.17 +module fb-drv
48.18 +module mag
48.19 +module dev_spi_jz4740
48.20 +module dev_backlight_spi_qi_lb60
48.21 +module dev_display_qi_lb60
48.22 +module dev_panel_qi_lb60
48.23 +module dev_cpm_jz4740
48.24 +module ex_qi_lb60_keypad
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/conf/landfall-examples/mips-qi_lb60-lcd-driver.cfg Sun May 13 01:34:16 2018 +0200
49.3 @@ -0,0 +1,100 @@
49.4 +-- vim: ft=lua ts=2 et sw=2
49.5 +
49.6 +-- Test LCD driver code. The target platform is the Ben NanoNote.
49.7 +
49.8 +local L4 = require("L4");
49.9 +
49.10 +local l = L4.default_loader;
49.11 +
49.12 +-- Define general access to peripherals.
49.13 +
49.14 +local io_buses = {
49.15 + cpm = l:new_channel();
49.16 + gpio = l:new_channel();
49.17 + lcd = l:new_channel();
49.18 + };
49.19 +
49.20 +l:start({
49.21 + caps = {
49.22 + cpm = io_buses.cpm:svr(),
49.23 + gpio = io_buses.gpio:svr(),
49.24 + lcd = io_buses.lcd:svr(),
49.25 +
49.26 + icu = L4.Env.icu,
49.27 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
49.28 + },
49.29 + },
49.30 + "rom/io rom/hw_devices.io rom/mips-qi_lb60-lcd-driver.io");
49.31 +
49.32 +-- Expose a SPI peripheral as a device.
49.33 +
49.34 +local spi = l:new_channel();
49.35 +
49.36 +l:startv({
49.37 + caps = {
49.38 + vbus = io_buses.gpio,
49.39 + spi = spi:svr(),
49.40 + },
49.41 + },
49.42 + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details
49.43 +
49.44 +-- Expose a SPI backlight device for the Ben.
49.45 +
49.46 +local backlight = l:new_channel(); -- exposes backlight device
49.47 +
49.48 +l:start({
49.49 + caps = {
49.50 + spi = spi,
49.51 + backlight = backlight:svr(),
49.52 + },
49.53 + },
49.54 + "rom/dev_backlight_spi_qi_lb60");
49.55 +
49.56 +-- Expose a display device for the Ben.
49.57 +
49.58 +local display = l:new_channel(); -- exposes display device
49.59 +
49.60 +l:start({
49.61 + caps = {
49.62 + backlight = backlight,
49.63 + display = display:svr(),
49.64 + vbus = io_buses.gpio,
49.65 + },
49.66 + },
49.67 + "rom/dev_display_qi_lb60");
49.68 +
49.69 +-- Expose a panel definition for the Ben.
49.70 +
49.71 +local panel = l:new_channel(); -- exposes panel
49.72 +
49.73 +l:start({
49.74 + caps = {
49.75 + panel = panel:svr(),
49.76 + },
49.77 + },
49.78 + "rom/dev_panel_qi_lb60");
49.79 +
49.80 +-- Expose the CPM peripheral.
49.81 +
49.82 +local cpm = l:new_channel();
49.83 +
49.84 +l:start({
49.85 + caps = {
49.86 + vbus = io_buses.cpm,
49.87 + cpm = cpm:svr(),
49.88 + },
49.89 + },
49.90 + "rom/dev_cpm_jz4740");
49.91 +
49.92 +-- Start and demonstrate the LCD driver.
49.93 +
49.94 +l:start({
49.95 + caps = {
49.96 + icu = L4.Env.icu,
49.97 + vbus = io_buses.lcd,
49.98 + cpm = cpm,
49.99 + display = display, -- needed by LCD driver
49.100 + panel = panel,
49.101 + },
49.102 + },
49.103 + "rom/ex_jz4740_lcd_driver");
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/conf/landfall-examples/mips-qi_lb60-lcd-driver.io Sun May 13 01:34:16 2018 +0200
50.3 @@ -0,0 +1,20 @@
50.4 +-- vim: ft=lua ts=2 et sw=2
50.5 +
50.6 +-- Configuration file for Io.
50.7 +
50.8 +local hw = Io.system_bus()
50.9 +
50.10 +Io.add_vbus("cpm", Io.Vi.System_bus
50.11 +{
50.12 + CPM = wrap(hw:match("jz4740-cpm"));
50.13 +})
50.14 +
50.15 +Io.add_vbus("gpio", Io.Vi.System_bus
50.16 +{
50.17 + GPIO = wrap(hw:match("jz4740-gpio"));
50.18 +})
50.19 +
50.20 +Io.add_vbus("lcd", Io.Vi.System_bus
50.21 +{
50.22 + LCD = wrap(hw:match("jz4740-lcd"));
50.23 +})
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/conf/landfall-examples/mips-qi_lb60-lcd-driver.list Sun May 13 01:34:16 2018 +0200
51.3 @@ -0,0 +1,19 @@
51.4 +
51.5 +modaddr 0x1100000
51.6 +
51.7 +entry mips-qi_lb60-lcd-driver-example
51.8 +bootstrap bootstrap -serial
51.9 +kernel fiasco -serial_esc
51.10 +roottask moe rom/mips-qi_lb60-lcd-driver.cfg
51.11 +module mips-qi_lb60-lcd-driver.cfg
51.12 +module mips-qi_lb60-lcd-driver.io
51.13 +module plat-qi_lb60/hw_devices.io
51.14 +module l4re
51.15 +module io
51.16 +module ned
51.17 +module dev_spi_jz4740
51.18 +module dev_backlight_spi_qi_lb60
51.19 +module dev_display_qi_lb60
51.20 +module dev_panel_qi_lb60
51.21 +module dev_cpm_jz4740
51.22 +module ex_jz4740_lcd_driver
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/conf/landfall-examples/mips-qi_lb60-lcd.cfg Sun May 13 01:34:16 2018 +0200
52.3 @@ -0,0 +1,30 @@
52.4 +-- vim: ft=lua ts=2 et sw=2
52.5 +
52.6 +-- Test LCD peripheral. The target platform is the Ben NanoNote.
52.7 +
52.8 +local L4 = require("L4");
52.9 +
52.10 +local l = L4.default_loader;
52.11 +
52.12 +local io_buses = {
52.13 + devices = l:new_channel(); -- exposes CPM, GPIO, LCD
52.14 + };
52.15 +
52.16 +l:start({
52.17 + caps = {
52.18 + devices = io_buses.devices:svr(),
52.19 + icu = L4.Env.icu,
52.20 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
52.21 + },
52.22 + log = { "IO", "y" },
52.23 + l4re_dbg = L4.Dbg.Warn,
52.24 + },
52.25 + "rom/io -vvvv rom/hw_devices.io rom/mips-qi_lb60-lcd.io");
52.26 +
52.27 +l:start({
52.28 + caps = {
52.29 + icu = L4.Env.icu,
52.30 + vbus = io_buses.devices,
52.31 + },
52.32 + },
52.33 + "rom/ex_qi_lb60_lcd");
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/conf/landfall-examples/mips-qi_lb60-lcd.io Sun May 13 01:34:16 2018 +0200
53.3 @@ -0,0 +1,12 @@
53.4 +-- vim: ft=lua ts=2 et sw=2
53.5 +
53.6 +-- Configuration file for Io.
53.7 +
53.8 +local hw = Io.system_bus()
53.9 +
53.10 +Io.add_vbus("devices", Io.Vi.System_bus
53.11 +{
53.12 + CPM = wrap(hw:match("jz4740-cpm"));
53.13 + GPIO = wrap(hw:match("jz4740-gpio"));
53.14 + LCD = wrap(hw:match("jz4740-lcd"));
53.15 +})
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/conf/landfall-examples/mips-qi_lb60-lcd.list Sun May 13 01:34:16 2018 +0200
54.3 @@ -0,0 +1,14 @@
54.4 +
54.5 +modaddr 0x1100000
54.6 +
54.7 +entry mips-qi_lb60-lcd-example
54.8 +bootstrap bootstrap -serial
54.9 +kernel fiasco -serial_esc
54.10 +roottask moe rom/mips-qi_lb60-lcd.cfg
54.11 +module mips-qi_lb60-lcd.cfg
54.12 +module mips-qi_lb60-lcd.io
54.13 +module plat-qi_lb60/hw_devices.io
54.14 +module l4re
54.15 +module io
54.16 +module ned
54.17 +module ex_qi_lb60_lcd
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/conf/landfall-examples/mips-qi_lb60-spectrum.cfg Sun May 13 01:34:16 2018 +0200
55.3 @@ -0,0 +1,130 @@
55.4 +-- vim: ft=lua ts=2 et sw=2
55.5 +
55.6 +-- Start Mag to multiplex the framebuffer showing only a single program.
55.7 +-- This example shows an animation showing off a spectrum of colours.
55.8 +-- The target platform is the Ben NanoNote.
55.9 +
55.10 +local L4 = require("L4");
55.11 +
55.12 +local l = L4.default_loader;
55.13 +
55.14 +-- Define general access to peripherals.
55.15 +
55.16 +local io_buses = {
55.17 + cpm = l:new_channel();
55.18 + gpio = l:new_channel();
55.19 + lcd = l:new_channel();
55.20 + };
55.21 +
55.22 +l:start({
55.23 + caps = {
55.24 + cpm = io_buses.cpm:svr(),
55.25 + gpio = io_buses.gpio:svr(),
55.26 + lcd = io_buses.lcd:svr(),
55.27 +
55.28 + icu = L4.Env.icu,
55.29 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
55.30 + },
55.31 + },
55.32 + "rom/io rom/hw_devices.io rom/mips-qi_lb60-spectrum.io");
55.33 +
55.34 +-- Expose a SPI peripheral as a device.
55.35 +
55.36 +local spi = l:new_channel();
55.37 +
55.38 +l:startv({
55.39 + caps = {
55.40 + vbus = io_buses.gpio,
55.41 + spi = spi:svr(),
55.42 + },
55.43 + },
55.44 + "rom/dev_spi_jz4740", "C23", "C22", "C21"); -- specifying clock, data, enable pin details
55.45 +
55.46 +-- Expose a SPI backlight device for the Ben.
55.47 +
55.48 +local backlight = l:new_channel(); -- exposes backlight device
55.49 +
55.50 +l:start({
55.51 + caps = {
55.52 + spi = spi,
55.53 + backlight = backlight:svr(),
55.54 + },
55.55 + },
55.56 + "rom/dev_backlight_spi_qi_lb60");
55.57 +
55.58 +-- Expose a display device for the Ben.
55.59 +
55.60 +local display = l:new_channel(); -- exposes display device
55.61 +
55.62 +l:start({
55.63 + caps = {
55.64 + backlight = backlight,
55.65 + display = display:svr(),
55.66 + vbus = io_buses.gpio,
55.67 + },
55.68 + },
55.69 + "rom/dev_display_qi_lb60");
55.70 +
55.71 +-- Expose a panel definition for the Ben.
55.72 +
55.73 +local panel = l:new_channel(); -- exposes panel
55.74 +
55.75 +l:start({
55.76 + caps = {
55.77 + panel = panel:svr(),
55.78 + },
55.79 + },
55.80 + "rom/dev_panel_qi_lb60");
55.81 +
55.82 +-- Expose the CPM peripheral.
55.83 +
55.84 +local cpm = l:new_channel();
55.85 +
55.86 +l:start({
55.87 + caps = {
55.88 + vbus = io_buses.cpm,
55.89 + cpm = cpm:svr(),
55.90 + },
55.91 + },
55.92 + "rom/dev_cpm_jz4740");
55.93 +
55.94 +-- Expose a framebuffer device.
55.95 +
55.96 +local fbdrv_fb = l:new_channel();
55.97 +
55.98 +l:start({
55.99 + caps = {
55.100 + vbus = io_buses.lcd,
55.101 + fb = fbdrv_fb:svr(),
55.102 + cpm = cpm,
55.103 + display = display, -- needed by LCD driver
55.104 + panel = panel,
55.105 + },
55.106 + },
55.107 + "rom/fb-drv");
55.108 +
55.109 +-- Multiplex the framebuffer.
55.110 +
55.111 +local mag_caps = {
55.112 + mag = l:new_channel(),
55.113 + svc = l:new_channel(),
55.114 + };
55.115 +
55.116 +l:start({
55.117 + caps = {
55.118 + vbus = io_buses.gpio, -- needed by input driver
55.119 + fb = fbdrv_fb,
55.120 + mag = mag_caps.mag:svr(),
55.121 + svc = mag_caps.svc:svr(),
55.122 + },
55.123 + },
55.124 + "rom/mag");
55.125 +
55.126 +-- Show the spectrum example.
55.127 +
55.128 +l:start({
55.129 + caps = {
55.130 + fb = mag_caps.svc:create(L4.Proto.Goos, "g=320x230", "barheight=10"),
55.131 + },
55.132 + },
55.133 + "rom/ex_fb_spectrum_cc");
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/conf/landfall-examples/mips-qi_lb60-spectrum.io Sun May 13 01:34:16 2018 +0200
56.3 @@ -0,0 +1,20 @@
56.4 +-- vim: ft=lua ts=2 et sw=2
56.5 +
56.6 +-- Configuration file for Io.
56.7 +
56.8 +local hw = Io.system_bus()
56.9 +
56.10 +Io.add_vbus("cpm", Io.Vi.System_bus
56.11 +{
56.12 + CPM = wrap(hw:match("jz4740-cpm"));
56.13 +})
56.14 +
56.15 +Io.add_vbus("gpio", Io.Vi.System_bus
56.16 +{
56.17 + GPIO = wrap(hw:match("jz4740-gpio"));
56.18 +})
56.19 +
56.20 +Io.add_vbus("lcd", Io.Vi.System_bus
56.21 +{
56.22 + LCD = wrap(hw:match("jz4740-lcd"));
56.23 +})
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/conf/landfall-examples/mips-qi_lb60-spectrum.list Sun May 13 01:34:16 2018 +0200
57.3 @@ -0,0 +1,21 @@
57.4 +
57.5 +modaddr 0x1100000
57.6 +
57.7 +entry mips-qi_lb60-spectrum-example
57.8 +bootstrap bootstrap -serial
57.9 +kernel fiasco -serial_esc
57.10 +roottask moe rom/mips-qi_lb60-spectrum.cfg
57.11 +module mips-qi_lb60-spectrum.cfg
57.12 +module mips-qi_lb60-spectrum.io
57.13 +module plat-qi_lb60/hw_devices.io
57.14 +module l4re
57.15 +module io
57.16 +module ned
57.17 +module fb-drv
57.18 +module mag
57.19 +module dev_spi_jz4740
57.20 +module dev_backlight_spi_qi_lb60
57.21 +module dev_display_qi_lb60
57.22 +module dev_panel_qi_lb60
57.23 +module dev_cpm_jz4740
57.24 +module ex_fb_spectrum_cc
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/docs/COPYING-GPL-2 Sun May 13 01:34:16 2018 +0200
58.3 @@ -0,0 +1,1 @@
58.4 +LICENCE.txt
58.5 \ No newline at end of file
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/docs/COPYING.txt Sun May 13 01:34:16 2018 +0200
59.3 @@ -0,0 +1,79 @@
59.4 +Licence Agreement
59.5 +-----------------
59.6 +
59.7 +All original work in this distribution is covered by the following
59.8 +copyright and licensing information:
59.9 +
59.10 +Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
59.11 +
59.12 +This software is free software; you can redistribute it and/or
59.13 +modify it under the terms of the GNU General Public License as
59.14 +published by the Free Software Foundation; either version 2 of
59.15 +the License, or (at your option) any later version.
59.16 +
59.17 +This software is distributed in the hope that it will be useful,
59.18 +but WITHOUT ANY WARRANTY; without even the implied warranty of
59.19 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59.20 +GNU General Public License for more details.
59.21 +
59.22 +You should have received a copy of the GNU General Public
59.23 +License along with this library; see the file LICENCE.txt
59.24 +If not, write to the Free Software Foundation, Inc.,
59.25 +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
59.26 +
59.27 +
59.28 +
59.29 +Other code has been incorporated into this distribution and is
59.30 +covered by the following copyrights:
59.31 +
59.32 +pkg/devices/lib/common/include:
59.33 +
59.34 + (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
59.35 +
59.36 +pkg/landfall-examples/qi_lb60_lcd:
59.37 +
59.38 + Copyright (C) 2001 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
59.39 + Copyright (C) 2005-2007, Ingenic Semiconductor Inc.
59.40 + Copyright (C) 2009 Qi Hardware Inc.
59.41 + Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
59.42 +
59.43 +Note that due to the incorporation of code from L4Re, the following
59.44 +files are actually licensed under the GPL version 2 only:
59.45 +
59.46 +pkg/devices/lib/common/include/hw_mmio_register_block.h
59.47 +pkg/devices/lib/common/include/hw_register_block.h
59.48 +pkg/devices/lib/gpio/include/gpio.h
59.49 +pkg/devices/lib/gpio/include/gpio-jz4730.h
59.50 +pkg/devices/lib/gpio/include/gpio-jz4740.h
59.51 +pkg/devices/lib/gpio/include/gpio-jz4780.h
59.52 +pkg/devices/lib/gpio/src/jz4730.cc
59.53 +pkg/devices/lib/gpio/src/jz4740.cc
59.54 +pkg/devices/lib/gpio/src/jz4780.cc
59.55 +
59.56 +No clear copyright statements are provided in the L4Re distribution
59.57 +for such files.
59.58 +
59.59 +
59.60 +
59.61 +Font definitions and licence (see unifont.tff for bitmap data
59.62 +derived from GNU Unifont's unifont.hex file):
59.63 +
59.64 +Copyright (C) 1998-2003 Roman Czyborra (http://czyborra.com/)
59.65 +
59.66 + All glyphs are released under the GNU General Public License
59.67 + (GPL) version 2 or (at your option) a later version, with the
59.68 + GNU font embedding exception:
59.69 +
59.70 + ** GPL v2.0 license with font embedding exception:
59.71 +
59.72 + As a special exception, if you create a document which
59.73 + uses this font, and embed this font or unaltered portions
59.74 + of this font into the document, this font does not by
59.75 + itself cause the resulting document to be covered by
59.76 + the GNU General Public License. This exception does not
59.77 + however invalidate any other reasons why the document
59.78 + might be covered by the GNU General Public License.
59.79 + If you modify this font, you may extend this exception
59.80 + to your version of the font, but you are not obligated
59.81 + to do so. If you do not wish to do so, delete this
59.82 + exception statement from your version.
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/docs/LICENCE.txt Sun May 13 01:34:16 2018 +0200
60.3 @@ -0,0 +1,339 @@
60.4 + GNU GENERAL PUBLIC LICENSE
60.5 + Version 2, June 1991
60.6 +
60.7 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
60.8 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60.9 + Everyone is permitted to copy and distribute verbatim copies
60.10 + of this license document, but changing it is not allowed.
60.11 +
60.12 + Preamble
60.13 +
60.14 + The licenses for most software are designed to take away your
60.15 +freedom to share and change it. By contrast, the GNU General Public
60.16 +License is intended to guarantee your freedom to share and change free
60.17 +software--to make sure the software is free for all its users. This
60.18 +General Public License applies to most of the Free Software
60.19 +Foundation's software and to any other program whose authors commit to
60.20 +using it. (Some other Free Software Foundation software is covered by
60.21 +the GNU Lesser General Public License instead.) You can apply it to
60.22 +your programs, too.
60.23 +
60.24 + When we speak of free software, we are referring to freedom, not
60.25 +price. Our General Public Licenses are designed to make sure that you
60.26 +have the freedom to distribute copies of free software (and charge for
60.27 +this service if you wish), that you receive source code or can get it
60.28 +if you want it, that you can change the software or use pieces of it
60.29 +in new free programs; and that you know you can do these things.
60.30 +
60.31 + To protect your rights, we need to make restrictions that forbid
60.32 +anyone to deny you these rights or to ask you to surrender the rights.
60.33 +These restrictions translate to certain responsibilities for you if you
60.34 +distribute copies of the software, or if you modify it.
60.35 +
60.36 + For example, if you distribute copies of such a program, whether
60.37 +gratis or for a fee, you must give the recipients all the rights that
60.38 +you have. You must make sure that they, too, receive or can get the
60.39 +source code. And you must show them these terms so they know their
60.40 +rights.
60.41 +
60.42 + We protect your rights with two steps: (1) copyright the software, and
60.43 +(2) offer you this license which gives you legal permission to copy,
60.44 +distribute and/or modify the software.
60.45 +
60.46 + Also, for each author's protection and ours, we want to make certain
60.47 +that everyone understands that there is no warranty for this free
60.48 +software. If the software is modified by someone else and passed on, we
60.49 +want its recipients to know that what they have is not the original, so
60.50 +that any problems introduced by others will not reflect on the original
60.51 +authors' reputations.
60.52 +
60.53 + Finally, any free program is threatened constantly by software
60.54 +patents. We wish to avoid the danger that redistributors of a free
60.55 +program will individually obtain patent licenses, in effect making the
60.56 +program proprietary. To prevent this, we have made it clear that any
60.57 +patent must be licensed for everyone's free use or not licensed at all.
60.58 +
60.59 + The precise terms and conditions for copying, distribution and
60.60 +modification follow.
60.61 +
60.62 + GNU GENERAL PUBLIC LICENSE
60.63 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
60.64 +
60.65 + 0. This License applies to any program or other work which contains
60.66 +a notice placed by the copyright holder saying it may be distributed
60.67 +under the terms of this General Public License. The "Program", below,
60.68 +refers to any such program or work, and a "work based on the Program"
60.69 +means either the Program or any derivative work under copyright law:
60.70 +that is to say, a work containing the Program or a portion of it,
60.71 +either verbatim or with modifications and/or translated into another
60.72 +language. (Hereinafter, translation is included without limitation in
60.73 +the term "modification".) Each licensee is addressed as "you".
60.74 +
60.75 +Activities other than copying, distribution and modification are not
60.76 +covered by this License; they are outside its scope. The act of
60.77 +running the Program is not restricted, and the output from the Program
60.78 +is covered only if its contents constitute a work based on the
60.79 +Program (independent of having been made by running the Program).
60.80 +Whether that is true depends on what the Program does.
60.81 +
60.82 + 1. You may copy and distribute verbatim copies of the Program's
60.83 +source code as you receive it, in any medium, provided that you
60.84 +conspicuously and appropriately publish on each copy an appropriate
60.85 +copyright notice and disclaimer of warranty; keep intact all the
60.86 +notices that refer to this License and to the absence of any warranty;
60.87 +and give any other recipients of the Program a copy of this License
60.88 +along with the Program.
60.89 +
60.90 +You may charge a fee for the physical act of transferring a copy, and
60.91 +you may at your option offer warranty protection in exchange for a fee.
60.92 +
60.93 + 2. You may modify your copy or copies of the Program or any portion
60.94 +of it, thus forming a work based on the Program, and copy and
60.95 +distribute such modifications or work under the terms of Section 1
60.96 +above, provided that you also meet all of these conditions:
60.97 +
60.98 + a) You must cause the modified files to carry prominent notices
60.99 + stating that you changed the files and the date of any change.
60.100 +
60.101 + b) You must cause any work that you distribute or publish, that in
60.102 + whole or in part contains or is derived from the Program or any
60.103 + part thereof, to be licensed as a whole at no charge to all third
60.104 + parties under the terms of this License.
60.105 +
60.106 + c) If the modified program normally reads commands interactively
60.107 + when run, you must cause it, when started running for such
60.108 + interactive use in the most ordinary way, to print or display an
60.109 + announcement including an appropriate copyright notice and a
60.110 + notice that there is no warranty (or else, saying that you provide
60.111 + a warranty) and that users may redistribute the program under
60.112 + these conditions, and telling the user how to view a copy of this
60.113 + License. (Exception: if the Program itself is interactive but
60.114 + does not normally print such an announcement, your work based on
60.115 + the Program is not required to print an announcement.)
60.116 +
60.117 +These requirements apply to the modified work as a whole. If
60.118 +identifiable sections of that work are not derived from the Program,
60.119 +and can be reasonably considered independent and separate works in
60.120 +themselves, then this License, and its terms, do not apply to those
60.121 +sections when you distribute them as separate works. But when you
60.122 +distribute the same sections as part of a whole which is a work based
60.123 +on the Program, the distribution of the whole must be on the terms of
60.124 +this License, whose permissions for other licensees extend to the
60.125 +entire whole, and thus to each and every part regardless of who wrote it.
60.126 +
60.127 +Thus, it is not the intent of this section to claim rights or contest
60.128 +your rights to work written entirely by you; rather, the intent is to
60.129 +exercise the right to control the distribution of derivative or
60.130 +collective works based on the Program.
60.131 +
60.132 +In addition, mere aggregation of another work not based on the Program
60.133 +with the Program (or with a work based on the Program) on a volume of
60.134 +a storage or distribution medium does not bring the other work under
60.135 +the scope of this License.
60.136 +
60.137 + 3. You may copy and distribute the Program (or a work based on it,
60.138 +under Section 2) in object code or executable form under the terms of
60.139 +Sections 1 and 2 above provided that you also do one of the following:
60.140 +
60.141 + a) Accompany it with the complete corresponding machine-readable
60.142 + source code, which must be distributed under the terms of Sections
60.143 + 1 and 2 above on a medium customarily used for software interchange; or,
60.144 +
60.145 + b) Accompany it with a written offer, valid for at least three
60.146 + years, to give any third party, for a charge no more than your
60.147 + cost of physically performing source distribution, a complete
60.148 + machine-readable copy of the corresponding source code, to be
60.149 + distributed under the terms of Sections 1 and 2 above on a medium
60.150 + customarily used for software interchange; or,
60.151 +
60.152 + c) Accompany it with the information you received as to the offer
60.153 + to distribute corresponding source code. (This alternative is
60.154 + allowed only for noncommercial distribution and only if you
60.155 + received the program in object code or executable form with such
60.156 + an offer, in accord with Subsection b above.)
60.157 +
60.158 +The source code for a work means the preferred form of the work for
60.159 +making modifications to it. For an executable work, complete source
60.160 +code means all the source code for all modules it contains, plus any
60.161 +associated interface definition files, plus the scripts used to
60.162 +control compilation and installation of the executable. However, as a
60.163 +special exception, the source code distributed need not include
60.164 +anything that is normally distributed (in either source or binary
60.165 +form) with the major components (compiler, kernel, and so on) of the
60.166 +operating system on which the executable runs, unless that component
60.167 +itself accompanies the executable.
60.168 +
60.169 +If distribution of executable or object code is made by offering
60.170 +access to copy from a designated place, then offering equivalent
60.171 +access to copy the source code from the same place counts as
60.172 +distribution of the source code, even though third parties are not
60.173 +compelled to copy the source along with the object code.
60.174 +
60.175 + 4. You may not copy, modify, sublicense, or distribute the Program
60.176 +except as expressly provided under this License. Any attempt
60.177 +otherwise to copy, modify, sublicense or distribute the Program is
60.178 +void, and will automatically terminate your rights under this License.
60.179 +However, parties who have received copies, or rights, from you under
60.180 +this License will not have their licenses terminated so long as such
60.181 +parties remain in full compliance.
60.182 +
60.183 + 5. You are not required to accept this License, since you have not
60.184 +signed it. However, nothing else grants you permission to modify or
60.185 +distribute the Program or its derivative works. These actions are
60.186 +prohibited by law if you do not accept this License. Therefore, by
60.187 +modifying or distributing the Program (or any work based on the
60.188 +Program), you indicate your acceptance of this License to do so, and
60.189 +all its terms and conditions for copying, distributing or modifying
60.190 +the Program or works based on it.
60.191 +
60.192 + 6. Each time you redistribute the Program (or any work based on the
60.193 +Program), the recipient automatically receives a license from the
60.194 +original licensor to copy, distribute or modify the Program subject to
60.195 +these terms and conditions. You may not impose any further
60.196 +restrictions on the recipients' exercise of the rights granted herein.
60.197 +You are not responsible for enforcing compliance by third parties to
60.198 +this License.
60.199 +
60.200 + 7. If, as a consequence of a court judgment or allegation of patent
60.201 +infringement or for any other reason (not limited to patent issues),
60.202 +conditions are imposed on you (whether by court order, agreement or
60.203 +otherwise) that contradict the conditions of this License, they do not
60.204 +excuse you from the conditions of this License. If you cannot
60.205 +distribute so as to satisfy simultaneously your obligations under this
60.206 +License and any other pertinent obligations, then as a consequence you
60.207 +may not distribute the Program at all. For example, if a patent
60.208 +license would not permit royalty-free redistribution of the Program by
60.209 +all those who receive copies directly or indirectly through you, then
60.210 +the only way you could satisfy both it and this License would be to
60.211 +refrain entirely from distribution of the Program.
60.212 +
60.213 +If any portion of this section is held invalid or unenforceable under
60.214 +any particular circumstance, the balance of the section is intended to
60.215 +apply and the section as a whole is intended to apply in other
60.216 +circumstances.
60.217 +
60.218 +It is not the purpose of this section to induce you to infringe any
60.219 +patents or other property right claims or to contest validity of any
60.220 +such claims; this section has the sole purpose of protecting the
60.221 +integrity of the free software distribution system, which is
60.222 +implemented by public license practices. Many people have made
60.223 +generous contributions to the wide range of software distributed
60.224 +through that system in reliance on consistent application of that
60.225 +system; it is up to the author/donor to decide if he or she is willing
60.226 +to distribute software through any other system and a licensee cannot
60.227 +impose that choice.
60.228 +
60.229 +This section is intended to make thoroughly clear what is believed to
60.230 +be a consequence of the rest of this License.
60.231 +
60.232 + 8. If the distribution and/or use of the Program is restricted in
60.233 +certain countries either by patents or by copyrighted interfaces, the
60.234 +original copyright holder who places the Program under this License
60.235 +may add an explicit geographical distribution limitation excluding
60.236 +those countries, so that distribution is permitted only in or among
60.237 +countries not thus excluded. In such case, this License incorporates
60.238 +the limitation as if written in the body of this License.
60.239 +
60.240 + 9. The Free Software Foundation may publish revised and/or new versions
60.241 +of the General Public License from time to time. Such new versions will
60.242 +be similar in spirit to the present version, but may differ in detail to
60.243 +address new problems or concerns.
60.244 +
60.245 +Each version is given a distinguishing version number. If the Program
60.246 +specifies a version number of this License which applies to it and "any
60.247 +later version", you have the option of following the terms and conditions
60.248 +either of that version or of any later version published by the Free
60.249 +Software Foundation. If the Program does not specify a version number of
60.250 +this License, you may choose any version ever published by the Free Software
60.251 +Foundation.
60.252 +
60.253 + 10. If you wish to incorporate parts of the Program into other free
60.254 +programs whose distribution conditions are different, write to the author
60.255 +to ask for permission. For software which is copyrighted by the Free
60.256 +Software Foundation, write to the Free Software Foundation; we sometimes
60.257 +make exceptions for this. Our decision will be guided by the two goals
60.258 +of preserving the free status of all derivatives of our free software and
60.259 +of promoting the sharing and reuse of software generally.
60.260 +
60.261 + NO WARRANTY
60.262 +
60.263 + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
60.264 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
60.265 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
60.266 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
60.267 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
60.268 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
60.269 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
60.270 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
60.271 +REPAIR OR CORRECTION.
60.272 +
60.273 + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
60.274 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
60.275 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
60.276 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
60.277 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
60.278 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
60.279 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
60.280 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
60.281 +POSSIBILITY OF SUCH DAMAGES.
60.282 +
60.283 + END OF TERMS AND CONDITIONS
60.284 +
60.285 + How to Apply These Terms to Your New Programs
60.286 +
60.287 + If you develop a new program, and you want it to be of the greatest
60.288 +possible use to the public, the best way to achieve this is to make it
60.289 +free software which everyone can redistribute and change under these terms.
60.290 +
60.291 + To do so, attach the following notices to the program. It is safest
60.292 +to attach them to the start of each source file to most effectively
60.293 +convey the exclusion of warranty; and each file should have at least
60.294 +the "copyright" line and a pointer to where the full notice is found.
60.295 +
60.296 + <one line to give the program's name and a brief idea of what it does.>
60.297 + Copyright (C) <year> <name of author>
60.298 +
60.299 + This program is free software; you can redistribute it and/or modify
60.300 + it under the terms of the GNU General Public License as published by
60.301 + the Free Software Foundation; either version 2 of the License, or
60.302 + (at your option) any later version.
60.303 +
60.304 + This program is distributed in the hope that it will be useful,
60.305 + but WITHOUT ANY WARRANTY; without even the implied warranty of
60.306 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60.307 + GNU General Public License for more details.
60.308 +
60.309 + You should have received a copy of the GNU General Public License along
60.310 + with this program; if not, write to the Free Software Foundation, Inc.,
60.311 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
60.312 +
60.313 +Also add information on how to contact you by electronic and paper mail.
60.314 +
60.315 +If the program is interactive, make it output a short notice like this
60.316 +when it starts in an interactive mode:
60.317 +
60.318 + Gnomovision version 69, Copyright (C) year name of author
60.319 + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
60.320 + This is free software, and you are welcome to redistribute it
60.321 + under certain conditions; type `show c' for details.
60.322 +
60.323 +The hypothetical commands `show w' and `show c' should show the appropriate
60.324 +parts of the General Public License. Of course, the commands you use may
60.325 +be called something other than `show w' and `show c'; they could even be
60.326 +mouse-clicks or menu items--whatever suits your program.
60.327 +
60.328 +You should also get your employer (if you work as a programmer) or your
60.329 +school, if any, to sign a "copyright disclaimer" for the program, if
60.330 +necessary. Here is a sample; alter the names:
60.331 +
60.332 + Yoyodyne, Inc., hereby disclaims all copyright interest in the program
60.333 + `Gnomovision' (which makes passes at compilers) written by James Hacker.
60.334 +
60.335 + <signature of Ty Coon>, 1 April 1989
60.336 + Ty Coon, President of Vice
60.337 +
60.338 +This General Public License does not permit incorporating your program into
60.339 +proprietary programs. If your program is a subroutine library, you may
60.340 +consider it more useful to permit linking proprietary applications with the
60.341 +library. If this is what you want to do, use the GNU Lesser General
60.342 +Public License instead of this License.
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/pkg/devices/Control Sun May 13 01:34:16 2018 +0200
61.3 @@ -0,0 +1,24 @@
61.4 +provides: libdrivers-common libdrivers-cpm libdrivers-gpio libdrivers-i2c libdrivers-pwm
61.5 +provides: libdrivers-keypad libdrivers-keypad-letux400 libdrivers-keypad-qi_lb60
61.6 +provides: libdrivers-lcd-jz4740
61.7 +provides: devices-backlight-pwm libdevice-backlight-client
61.8 +provides: devices-cpm-jz4730 devices-cpm-jz4740 devices-cpm-jz4780
61.9 +provides: libdevice-cpm-client libdevice-cpm-ops
61.10 +provides: libdevice-cpm-server
61.11 +provides: devices-display-letux400 devices-display-qi_lb60
61.12 +provides: libdevice-display-client libdevice-display-ops
61.13 +provides: devices-fb-jz4740
61.14 +provides: libdevice-fb-client libdevice-fb-ops
61.15 +provides: libdevice-fb-lcd libdevice-fb-server
61.16 +provides: libdevice-input-keypad
61.17 +provides: devices-keypad-letux400 devices-keypad-qi_lb60
61.18 +provides: libdevice-keypad-client libdevice-keypad-ops
61.19 +provides: libdevice-keypad-server
61.20 +provides: libdevice-lcd libdevice-lcd-jz4740
61.21 +provides: devices-panel-letux400 devices-panel-qi_lb60
61.22 +provides: libdevice-panel-client libdevice-panel-ops
61.23 +provides: devices-pwm-jz4730 libdevice-pwm-client
61.24 +provides: devices-spi-jz4740 libdevice-spi-client
61.25 +provides: libdevice-util
61.26 +requires: libc l4re_c libio
61.27 +Maintainer: paul@boddie.org.uk
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/pkg/devices/Makefile Sun May 13 01:34:16 2018 +0200
62.3 @@ -0,0 +1,21 @@
62.4 +PKGDIR = .
62.5 +L4DIR ?= $(PKGDIR)/../..
62.6 +
62.7 +TARGET = backlight cpm display fb input keypad lcd lib panel pwm spi util
62.8 +
62.9 +include $(L4DIR)/mk/subdir.mk
62.10 +
62.11 +# Internal dependencies.
62.12 +# lib provides driver libraries
62.13 +# util provides peripheral memory access
62.14 +
62.15 +backlight: pwm spi
62.16 +cpm: lib util
62.17 +display: backlight lib util
62.18 +fb: lcd lib util
62.19 +input: keypad lib
62.20 +keypad: lib util
62.21 +lcd: display panel lib util
62.22 +panel: lib
62.23 +pwm: lib util
62.24 +spi: lib util
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/pkg/devices/backlight/Makefile Sun May 13 01:34:16 2018 +0200
63.3 @@ -0,0 +1,8 @@
63.4 +PKGDIR ?= ..
63.5 +L4DIR ?= $(PKGDIR)/../..
63.6 +
63.7 +TARGET := include src
63.8 +
63.9 +include $(L4DIR)/mk/subdir.mk
63.10 +
63.11 +src: include
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/pkg/devices/backlight/include/Makefile Sun May 13 01:34:16 2018 +0200
64.3 @@ -0,0 +1,4 @@
64.4 +PKGDIR = ../..
64.5 +L4DIR ?= $(PKGDIR)/../..
64.6 +
64.7 +include $(L4DIR)/mk/include.mk
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/pkg/devices/backlight/include/backlight-client.h Sun May 13 01:34:16 2018 +0200
65.3 @@ -0,0 +1,39 @@
65.4 +/*
65.5 + * Backlight client to access backlight servers.
65.6 + *
65.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
65.8 + *
65.9 + * This program is free software; you can redistribute it and/or
65.10 + * modify it under the terms of the GNU General Public License as
65.11 + * published by the Free Software Foundation; either version 2 of
65.12 + * the License, or (at your option) any later version.
65.13 + *
65.14 + * This program is distributed in the hope that it will be useful,
65.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
65.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65.17 + * GNU General Public License for more details.
65.18 + *
65.19 + * You should have received a copy of the GNU General Public License
65.20 + * along with this program; if not, write to the Free Software
65.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
65.22 + * Boston, MA 02110-1301, USA
65.23 + */
65.24 +
65.25 +#pragma once
65.26 +
65.27 +#ifdef __cplusplus
65.28 +
65.29 +#include <l4/re/env>
65.30 +#include "backlight-ops.h"
65.31 +
65.32 +class Backlight_device_interface : public L4::Kobject_t<Backlight_device_interface, L4::Kobject>
65.33 +{
65.34 + L4_KOBJECT(Backlight_device_interface)
65.35 +
65.36 +public:
65.37 + int disable() throw();
65.38 + int enable() throw();
65.39 + int set_brightness(int level) throw();
65.40 +};
65.41 +
65.42 +#endif
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/pkg/devices/backlight/include/backlight-ops.h Sun May 13 01:34:16 2018 +0200
66.3 @@ -0,0 +1,24 @@
66.4 +/*
66.5 + * Backlight server operations.
66.6 + *
66.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
66.8 + *
66.9 + * This program is free software; you can redistribute it and/or
66.10 + * modify it under the terms of the GNU General Public License as
66.11 + * published by the Free Software Foundation; either version 2 of
66.12 + * the License, or (at your option) any later version.
66.13 + *
66.14 + * This program is distributed in the hope that it will be useful,
66.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
66.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66.17 + * GNU General Public License for more details.
66.18 + *
66.19 + * You should have received a copy of the GNU General Public License
66.20 + * along with this program; if not, write to the Free Software
66.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
66.22 + * Boston, MA 02110-1301, USA
66.23 + */
66.24 +
66.25 +#pragma once
66.26 +
66.27 +enum { Backlight_op_disable, Backlight_op_enable, Backlight_op_set_brightness };
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/pkg/devices/backlight/src/Makefile Sun May 13 01:34:16 2018 +0200
67.3 @@ -0,0 +1,6 @@
67.4 +PKGDIR ?= ../..
67.5 +L4DIR ?= $(PKGDIR)/../..
67.6 +
67.7 +TARGET := client pwm spi-qi_lb60
67.8 +
67.9 +include $(L4DIR)/mk/subdir.mk
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/pkg/devices/backlight/src/client/Makefile Sun May 13 01:34:16 2018 +0200
68.3 @@ -0,0 +1,13 @@
68.4 +PKGDIR ?= ../../..
68.5 +L4DIR ?= $(PKGDIR)/../..
68.6 +
68.7 +TARGET = libdevice_backlight_client.o.a
68.8 +PC_FILENAME := libdevice-backlight-client
68.9 +
68.10 +SRC_CC := backlight-client.cc
68.11 +
68.12 +PRIVATE_INCDIR += $(PKGDIR)/backlight/include
68.13 +
68.14 +REQUIRES_LIBS := l4re_c l4re_c-util
68.15 +
68.16 +include $(L4DIR)/mk/lib.mk
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/pkg/devices/backlight/src/client/backlight-client.cc Sun May 13 01:34:16 2018 +0200
69.3 @@ -0,0 +1,50 @@
69.4 +/*
69.5 + * Backlight client to access backlight servers.
69.6 + *
69.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
69.8 + *
69.9 + * This program is free software; you can redistribute it and/or
69.10 + * modify it under the terms of the GNU General Public License as
69.11 + * published by the Free Software Foundation; either version 2 of
69.12 + * the License, or (at your option) any later version.
69.13 + *
69.14 + * This program is distributed in the hope that it will be useful,
69.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
69.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69.17 + * GNU General Public License for more details.
69.18 + *
69.19 + * You should have received a copy of the GNU General Public License
69.20 + * along with this program; if not, write to the Free Software
69.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
69.22 + * Boston, MA 02110-1301, USA
69.23 + */
69.24 +
69.25 +#include <l4/cxx/ipc_stream>
69.26 +#include <l4/re/env>
69.27 +
69.28 +#include "backlight-client.h"
69.29 +
69.30 +int
69.31 +Backlight_device_interface::disable() throw()
69.32 +{
69.33 + L4::Ipc::Iostream s(l4_utcb());
69.34 +
69.35 + return l4_error(s.call(cap(), Backlight_op_disable));
69.36 +}
69.37 +
69.38 +int
69.39 +Backlight_device_interface::enable() throw()
69.40 +{
69.41 + L4::Ipc::Iostream s(l4_utcb());
69.42 +
69.43 + return l4_error(s.call(cap(), Backlight_op_enable));
69.44 +}
69.45 +
69.46 +int
69.47 +Backlight_device_interface::set_brightness(int level) throw()
69.48 +{
69.49 + L4::Ipc::Iostream s(l4_utcb());
69.50 +
69.51 + s << level;
69.52 + return l4_error(s.call(cap(), Backlight_op_set_brightness));
69.53 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/pkg/devices/backlight/src/pwm/Makefile Sun May 13 01:34:16 2018 +0200
70.3 @@ -0,0 +1,13 @@
70.4 +PKGDIR ?= ../../..
70.5 +L4DIR ?= $(PKGDIR)/../..
70.6 +
70.7 +TARGET = dev_backlight_pwm
70.8 +PC_FILENAME := devices-backlight-pwm
70.9 +
70.10 +SRC_CC := backlight-pwm.cc
70.11 +
70.12 +PRIVATE_INCDIR += $(PKGDIR)/backlight/include
70.13 +
70.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-pwm-client
70.15 +
70.16 +include $(L4DIR)/mk/prog.mk
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/pkg/devices/backlight/src/pwm/backlight-pwm.cc Sun May 13 01:34:16 2018 +0200
71.3 @@ -0,0 +1,128 @@
71.4 +/*
71.5 + * Access a PWM server to update a display panel backlight.
71.6 + *
71.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
71.8 + *
71.9 + * This program is free software; you can redistribute it and/or
71.10 + * modify it under the terms of the GNU General Public License as
71.11 + * published by the Free Software Foundation; either version 2 of
71.12 + * the License, or (at your option) any later version.
71.13 + *
71.14 + * This program is distributed in the hope that it will be useful,
71.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
71.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71.17 + * GNU General Public License for more details.
71.18 + *
71.19 + * You should have received a copy of the GNU General Public License
71.20 + * along with this program; if not, write to the Free Software
71.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
71.22 + * Boston, MA 02110-1301, USA
71.23 + */
71.24 +
71.25 +#include <l4/cxx/ipc_server>
71.26 +#include <l4/re/env>
71.27 +#include <l4/re/util/object_registry>
71.28 +#include <l4/sys/capability>
71.29 +
71.30 +#include <stdlib.h>
71.31 +
71.32 +#include <l4/devices/pwm-client.h>
71.33 +#include "backlight-ops.h"
71.34 +
71.35 +/* PWM access abstractions. */
71.36 +
71.37 +static L4::Cap<Pwm_device_interface> pwm_device;
71.38 +
71.39 +
71.40 +
71.41 +/* Backlight device. */
71.42 +
71.43 +class Backlight_device_server : public L4::Server_object_t<L4::Kobject>
71.44 +{
71.45 + int _min, _max;
71.46 +
71.47 +public:
71.48 + explicit Backlight_device_server(int min, int max)
71.49 + : _min(min), _max(max)
71.50 + {
71.51 + }
71.52 +
71.53 + /* Dispatch incoming requests. */
71.54 +
71.55 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
71.56 + {
71.57 + l4_msgtag_t tag;
71.58 + int arg;
71.59 +
71.60 + (void) obj;
71.61 + ios >> tag;
71.62 +
71.63 + switch (tag.label())
71.64 + {
71.65 + case Backlight_op_disable:
71.66 + disable();
71.67 + return L4_EOK;
71.68 +
71.69 + case Backlight_op_enable:
71.70 + enable();
71.71 + return L4_EOK;
71.72 +
71.73 + case Backlight_op_set_brightness:
71.74 + ios >> arg;
71.75 + set_brightness(arg);
71.76 + return L4_EOK;
71.77 +
71.78 + default:
71.79 + return -L4_EBADPROTO;
71.80 + }
71.81 + }
71.82 +
71.83 + void disable()
71.84 + {
71.85 + pwm_device->disable();
71.86 + }
71.87 +
71.88 + void enable()
71.89 + {
71.90 + pwm_device->enable();
71.91 + }
71.92 +
71.93 + /* Use the PWM device to update the backlight level. */
71.94 +
71.95 + void set_brightness(int level)
71.96 + {
71.97 + pwm_device->set_duty(level);
71.98 + }
71.99 +};
71.100 +
71.101 +static L4Re::Util::Registry_server<> server;
71.102 +
71.103 +
71.104 +
71.105 +/* Arguments: <minimum level> <maximum level> */
71.106 +
71.107 +int main(int argc, char *argv[])
71.108 +{
71.109 + int min, max;
71.110 +
71.111 + if (argc < 3)
71.112 + return 1;
71.113 +
71.114 + /* Obtain a reference to the PWM device. */
71.115 +
71.116 + pwm_device = L4Re::Env::env()->get_cap<Pwm_device_interface>("pwm");
71.117 + if (!pwm_device.is_valid()) return 1;
71.118 +
71.119 + /* Initialise and register a new server object. */
71.120 +
71.121 + min = atoi(argv[1]);
71.122 + max = atoi(argv[2]);
71.123 +
71.124 + Backlight_device_server server_obj(min, max);
71.125 + server.registry()->register_obj(&server_obj, "backlight");
71.126 +
71.127 + /* Enter the IPC server loop. */
71.128 +
71.129 + server.loop();
71.130 + return 0;
71.131 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/pkg/devices/backlight/src/spi-qi_lb60/Makefile Sun May 13 01:34:16 2018 +0200
72.3 @@ -0,0 +1,13 @@
72.4 +PKGDIR ?= ../../..
72.5 +L4DIR ?= $(PKGDIR)/../..
72.6 +
72.7 +TARGET = dev_backlight_spi_qi_lb60
72.8 +PC_FILENAME := devices-backlight-spi-qi_lb60
72.9 +
72.10 +SRC_CC := backlight-spi-qi_lb60.cc
72.11 +
72.12 +PRIVATE_INCDIR += $(PKGDIR)/backlight/include
72.13 +
72.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-spi-client
72.15 +
72.16 +include $(L4DIR)/mk/prog.mk
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/pkg/devices/backlight/src/spi-qi_lb60/backlight-spi-qi_lb60.cc Sun May 13 01:34:16 2018 +0200
73.3 @@ -0,0 +1,130 @@
73.4 +/*
73.5 + * Access a SPI server to update a display panel backlight.
73.6 + * This server is specific to the Ben NanoNote.
73.7 + *
73.8 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
73.9 + *
73.10 + * This program is free software; you can redistribute it and/or
73.11 + * modify it under the terms of the GNU General Public License as
73.12 + * published by the Free Software Foundation; either version 2 of
73.13 + * the License, or (at your option) any later version.
73.14 + *
73.15 + * This program is distributed in the hope that it will be useful,
73.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
73.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73.18 + * GNU General Public License for more details.
73.19 + *
73.20 + * You should have received a copy of the GNU General Public License
73.21 + * along with this program; if not, write to the Free Software
73.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
73.23 + * Boston, MA 02110-1301, USA
73.24 + */
73.25 +
73.26 +#include <l4/cxx/ipc_server>
73.27 +#include <l4/re/env>
73.28 +#include <l4/re/util/object_registry>
73.29 +#include <l4/sys/capability>
73.30 +
73.31 +#include <stdlib.h>
73.32 +
73.33 +#include <l4/devices/spi-client.h>
73.34 +#include "backlight-ops.h"
73.35 +
73.36 +/* SPI access abstractions. */
73.37 +
73.38 +static L4::Cap<Spi_device_interface> spi_device;
73.39 +
73.40 +
73.41 +
73.42 +/* Backlight device. */
73.43 +
73.44 +class Backlight_device_server : public L4::Server_object_t<L4::Kobject>
73.45 +{
73.46 + int _min = 55, _max = 90, _start = 70;
73.47 +
73.48 + void set_duty(int level)
73.49 + {
73.50 + level = level < _min ? _min : (level > _max ? _max : level);
73.51 +
73.52 + /* PWM_DUTY = R05h<5:3> = 5% increments from min to max */
73.53 +
73.54 + int duty = ((level - _min) / 5) << 3;
73.55 +
73.56 + spi_device->send(16, 0x0516 | duty); /* R05h: GRB=0 (reset); PWM_DUTY=duty; SHDB2=1, SHDB1=1 (power-related); STB=0 (standby) */
73.57 + spi_device->send(16, 0x0546 | duty); /* R05h: GRB=1 (normal operation); ... */
73.58 + spi_device->send(16, 0x078d); /* R07h: HBLK=141 (horizontal blanking period from start of hsync pulse to data start) */
73.59 + spi_device->send(16, 0x1301); /* R13h: IN_SEL=1 (alignment mode) */
73.60 + spi_device->send(16, 0x0547 | duty); /* R05h: ...; STB=1 (not standby) */
73.61 + }
73.62 +
73.63 +public:
73.64 + /* Dispatch incoming requests. */
73.65 +
73.66 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
73.67 + {
73.68 + l4_msgtag_t tag;
73.69 + int arg;
73.70 +
73.71 + (void) obj;
73.72 + ios >> tag;
73.73 +
73.74 + switch (tag.label())
73.75 + {
73.76 + case Backlight_op_disable:
73.77 + disable();
73.78 + return L4_EOK;
73.79 +
73.80 + case Backlight_op_enable:
73.81 + enable();
73.82 + return L4_EOK;
73.83 +
73.84 + case Backlight_op_set_brightness:
73.85 + ios >> arg;
73.86 + set_brightness(arg);
73.87 + return L4_EOK;
73.88 +
73.89 + default:
73.90 + return -L4_EBADPROTO;
73.91 + }
73.92 + }
73.93 +
73.94 + void disable()
73.95 + {
73.96 + spi_device->send(16, 0x055e);
73.97 + }
73.98 +
73.99 + void enable()
73.100 + {
73.101 + set_duty(_start);
73.102 + }
73.103 +
73.104 + /* Use the SPI device to update the brightness level. */
73.105 +
73.106 + void set_brightness(int level)
73.107 + {
73.108 + level = level < _min ? _min : (level > _max ? _max : level);
73.109 + spi_device->send(16, 0x0300 | level); /* R03h: brightness */
73.110 + }
73.111 +};
73.112 +
73.113 +static L4Re::Util::Registry_server<> server;
73.114 +
73.115 +
73.116 +
73.117 +int main(void)
73.118 +{
73.119 + /* Obtain a reference to the SPI device. */
73.120 +
73.121 + spi_device = L4Re::Env::env()->get_cap<Spi_device_interface>("spi");
73.122 + if (!spi_device.is_valid()) return 1;
73.123 +
73.124 + /* Initialise and register a new server object. */
73.125 +
73.126 + Backlight_device_server server_obj;
73.127 + server.registry()->register_obj(&server_obj, "backlight");
73.128 +
73.129 + /* Enter the IPC server loop. */
73.130 +
73.131 + server.loop();
73.132 + return 0;
73.133 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/pkg/devices/cpm/Makefile Sun May 13 01:34:16 2018 +0200
74.3 @@ -0,0 +1,8 @@
74.4 +PKGDIR ?= ..
74.5 +L4DIR ?= $(PKGDIR)/../..
74.6 +
74.7 +TARGET := include src
74.8 +
74.9 +include $(L4DIR)/mk/subdir.mk
74.10 +
74.11 +src: include
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/pkg/devices/cpm/include/Makefile Sun May 13 01:34:16 2018 +0200
75.3 @@ -0,0 +1,4 @@
75.4 +PKGDIR = ../..
75.5 +L4DIR ?= $(PKGDIR)/../..
75.6 +
75.7 +include $(L4DIR)/mk/include.mk
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/pkg/devices/cpm/include/cpm-client.h Sun May 13 01:34:16 2018 +0200
76.3 @@ -0,0 +1,40 @@
76.4 +/*
76.5 + * CPM client to access CPM servers.
76.6 + *
76.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
76.8 + *
76.9 + * This program is free software; you can redistribute it and/or
76.10 + * modify it under the terms of the GNU General Public License as
76.11 + * published by the Free Software Foundation; either version 2 of
76.12 + * the License, or (at your option) any later version.
76.13 + *
76.14 + * This program is distributed in the hope that it will be useful,
76.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
76.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
76.17 + * GNU General Public License for more details.
76.18 + *
76.19 + * You should have received a copy of the GNU General Public License
76.20 + * along with this program; if not, write to the Free Software
76.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
76.22 + * Boston, MA 02110-1301, USA
76.23 + */
76.24 +
76.25 +#pragma once
76.26 +
76.27 +#ifdef __cplusplus
76.28 +
76.29 +#include <l4/re/env>
76.30 +#include <stdint.h>
76.31 +
76.32 +class Cpm_device_interface : public L4::Kobject_t<Cpm_device_interface, L4::Kobject>
76.33 +{
76.34 + L4_KOBJECT(Cpm_device_interface)
76.35 +
76.36 +public:
76.37 + int set_lcd_frequencies(uint32_t pclk, uint8_t multiplier) throw();
76.38 + int start_lcd() throw();
76.39 + int stop_lcd() throw();
76.40 + int update_output_frequency() throw();
76.41 +};
76.42 +
76.43 +#endif
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/pkg/devices/cpm/include/cpm-ops.h Sun May 13 01:34:16 2018 +0200
77.3 @@ -0,0 +1,29 @@
77.4 +/*
77.5 + * CPM server operations.
77.6 + *
77.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
77.8 + *
77.9 + * This program is free software; you can redistribute it and/or
77.10 + * modify it under the terms of the GNU General Public License as
77.11 + * published by the Free Software Foundation; either version 2 of
77.12 + * the License, or (at your option) any later version.
77.13 + *
77.14 + * This program is distributed in the hope that it will be useful,
77.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
77.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77.17 + * GNU General Public License for more details.
77.18 + *
77.19 + * You should have received a copy of the GNU General Public License
77.20 + * along with this program; if not, write to the Free Software
77.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
77.22 + * Boston, MA 02110-1301, USA
77.23 + */
77.24 +
77.25 +#pragma once
77.26 +
77.27 +enum {
77.28 + Cpm_op_set_lcd_frequencies,
77.29 + Cpm_op_start_lcd,
77.30 + Cpm_op_stop_lcd,
77.31 + Cpm_op_update_output_frequency,
77.32 +};
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/pkg/devices/cpm/include/cpm-server.h Sun May 13 01:34:16 2018 +0200
78.3 @@ -0,0 +1,49 @@
78.4 +/*
78.5 + * Common CPM server functionality.
78.6 + *
78.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
78.8 + *
78.9 + * This program is free software; you can redistribute it and/or
78.10 + * modify it under the terms of the GNU General Public License as
78.11 + * published by the Free Software Foundation; either version 2 of
78.12 + * the License, or (at your option) any later version.
78.13 + *
78.14 + * This program is distributed in the hope that it will be useful,
78.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
78.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78.17 + * GNU General Public License for more details.
78.18 + *
78.19 + * You should have received a copy of the GNU General Public License
78.20 + * along with this program; if not, write to the Free Software
78.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
78.22 + * Boston, MA 02110-1301, USA
78.23 + */
78.24 +
78.25 +#pragma once
78.26 +
78.27 +#include <l4/devices/cpm.h>
78.28 +
78.29 +#ifdef __cplusplus
78.30 +
78.31 +#include <l4/cxx/ipc_server>
78.32 +#include <l4/re/dataspace>
78.33 +#include <l4/re/env>
78.34 +
78.35 +/* Server object to provide CPM access. */
78.36 +
78.37 +class Cpm_server : public L4::Server_object_t<L4::Kobject>
78.38 +{
78.39 +private:
78.40 + Cpm_chip *_chip;
78.41 +
78.42 +public:
78.43 + /* Initialise the server with a peripheral reference. */
78.44 +
78.45 + explicit Cpm_server(Cpm_chip *chip)
78.46 + : _chip(chip)
78.47 + {}
78.48 +
78.49 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
78.50 +};
78.51 +
78.52 +#endif
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/pkg/devices/cpm/src/Makefile Sun May 13 01:34:16 2018 +0200
79.3 @@ -0,0 +1,10 @@
79.4 +PKGDIR ?= ../..
79.5 +L4DIR ?= $(PKGDIR)/../..
79.6 +
79.7 +TARGET := client jz4730 jz4740 jz4780 server
79.8 +
79.9 +include $(L4DIR)/mk/subdir.mk
79.10 +
79.11 +jz4730: server
79.12 +jz4740: server
79.13 +jz4780: server
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/pkg/devices/cpm/src/client/Makefile Sun May 13 01:34:16 2018 +0200
80.3 @@ -0,0 +1,13 @@
80.4 +PKGDIR ?= ../../..
80.5 +L4DIR ?= $(PKGDIR)/../..
80.6 +
80.7 +TARGET = libdevice_cpm_client.o.a
80.8 +PC_FILENAME := libdevice-cpm-client
80.9 +
80.10 +SRC_CC := cpm-client.cc
80.11 +
80.12 +PRIVATE_INCDIR += $(PKGDIR)/cpm/include
80.13 +
80.14 +REQUIRES_LIBS := l4re_c l4re_c-util
80.15 +
80.16 +include $(L4DIR)/mk/lib.mk
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
81.2 +++ b/pkg/devices/cpm/src/client/cpm-client.cc Sun May 13 01:34:16 2018 +0200
81.3 @@ -0,0 +1,60 @@
81.4 +/*
81.5 + * CPM client to access CPM servers.
81.6 + *
81.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
81.8 + *
81.9 + * This program is free software; you can redistribute it and/or
81.10 + * modify it under the terms of the GNU General Public License as
81.11 + * published by the Free Software Foundation; either version 2 of
81.12 + * the License, or (at your option) any later version.
81.13 + *
81.14 + * This program is distributed in the hope that it will be useful,
81.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
81.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81.17 + * GNU General Public License for more details.
81.18 + *
81.19 + * You should have received a copy of the GNU General Public License
81.20 + * along with this program; if not, write to the Free Software
81.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
81.22 + * Boston, MA 02110-1301, USA
81.23 + */
81.24 +
81.25 +#include <l4/cxx/ipc_stream>
81.26 +#include <l4/re/env>
81.27 +
81.28 +#include "cpm-client.h"
81.29 +#include "cpm-ops.h"
81.30 +
81.31 +int
81.32 +Cpm_device_interface::set_lcd_frequencies(uint32_t pclk, uint8_t multiplier) throw()
81.33 +{
81.34 + L4::Ipc::Iostream s(l4_utcb());
81.35 +
81.36 + s << pclk << multiplier;
81.37 +
81.38 + return l4_error(s.call(cap(), Cpm_op_set_lcd_frequencies));
81.39 +}
81.40 +
81.41 +int
81.42 +Cpm_device_interface::start_lcd() throw()
81.43 +{
81.44 + L4::Ipc::Iostream s(l4_utcb());
81.45 +
81.46 + return l4_error(s.call(cap(), Cpm_op_start_lcd));
81.47 +}
81.48 +
81.49 +int
81.50 +Cpm_device_interface::stop_lcd() throw()
81.51 +{
81.52 + L4::Ipc::Iostream s(l4_utcb());
81.53 +
81.54 + return l4_error(s.call(cap(), Cpm_op_stop_lcd));
81.55 +}
81.56 +
81.57 +int
81.58 +Cpm_device_interface::update_output_frequency() throw()
81.59 +{
81.60 + L4::Ipc::Iostream s(l4_utcb());
81.61 +
81.62 + return l4_error(s.call(cap(), Cpm_op_update_output_frequency));
81.63 +}
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/pkg/devices/cpm/src/jz4730/Makefile Sun May 13 01:34:16 2018 +0200
82.3 @@ -0,0 +1,13 @@
82.4 +PKGDIR ?= ../../..
82.5 +L4DIR ?= $(PKGDIR)/../..
82.6 +
82.7 +TARGET = dev_cpm_jz4730
82.8 +PC_FILENAME := devices-cpm-jz4730
82.9 +
82.10 +SRC_CC := cpm-jz4730.cc
82.11 +
82.12 +PRIVATE_INCDIR += $(PKGDIR)/cpm/include
82.13 +
82.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-cpm libdevice-cpm-server libdevice-util
82.15 +
82.16 +include $(L4DIR)/mk/prog.mk
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc Sun May 13 01:34:16 2018 +0200
83.3 @@ -0,0 +1,73 @@
83.4 +/*
83.5 + * JZ4730 CPM server.
83.6 + *
83.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
83.8 + *
83.9 + * This program is free software; you can redistribute it and/or
83.10 + * modify it under the terms of the GNU General Public License as
83.11 + * published by the Free Software Foundation; either version 2 of
83.12 + * the License, or (at your option) any later version.
83.13 + *
83.14 + * This program is distributed in the hope that it will be useful,
83.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
83.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83.17 + * GNU General Public License for more details.
83.18 + *
83.19 + * You should have received a copy of the GNU General Public License
83.20 + * along with this program; if not, write to the Free Software
83.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
83.22 + * Boston, MA 02110-1301, USA
83.23 + */
83.24 +
83.25 +#include <l4/devices/cpm-jz4730.h>
83.26 +#include <l4/devices/memory.h>
83.27 +#include "cpm-server.h"
83.28 +
83.29 +#include <l4/re/dataspace>
83.30 +#include <l4/re/env>
83.31 +#include <l4/re/util/object_registry>
83.32 +
83.33 +#include <l4/sys/types.h>
83.34 +
83.35 +// Virtual addresses for the CPM and LCD register blocks.
83.36 +
83.37 +static l4_addr_t cpm_virt_base = 0, cpm_virt_base_end = 0;
83.38 +
83.39 +
83.40 +
83.41 +// Access to peripheral memory.
83.42 +
83.43 +static int setup_memory()
83.44 +{
83.45 + if (get_memory("jz4730-cpm", &cpm_virt_base, &cpm_virt_base_end))
83.46 + return 1;
83.47 +
83.48 + return 0;
83.49 +}
83.50 +
83.51 +
83.52 +
83.53 +static L4Re::Util::Registry_server<> server;
83.54 +
83.55 +
83.56 +
83.57 +/* Main program. */
83.58 +
83.59 +int main(void)
83.60 +{
83.61 + if (setup_memory()) return 1;
83.62 +
83.63 + /* Initialise the CPM abstraction. */
83.64 +
83.65 + Cpm_jz4730_chip cpm_device(cpm_virt_base, 3686400);
83.66 +
83.67 + /* Initialise and register a server object. */
83.68 +
83.69 + Cpm_server server_obj(&cpm_device);
83.70 + server.registry()->register_obj(&server_obj, "cpm");
83.71 +
83.72 + /* Enter the IPC server loop. */
83.73 +
83.74 + server.loop();
83.75 + return 0;
83.76 +}
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/pkg/devices/cpm/src/jz4740/Makefile Sun May 13 01:34:16 2018 +0200
84.3 @@ -0,0 +1,13 @@
84.4 +PKGDIR ?= ../../..
84.5 +L4DIR ?= $(PKGDIR)/../..
84.6 +
84.7 +TARGET = dev_cpm_jz4740
84.8 +PC_FILENAME := devices-cpm-jz4740
84.9 +
84.10 +SRC_CC := cpm-jz4740.cc
84.11 +
84.12 +PRIVATE_INCDIR += $(PKGDIR)/cpm/include
84.13 +
84.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-cpm libdevice-cpm-server libdevice-util
84.15 +
84.16 +include $(L4DIR)/mk/prog.mk
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/pkg/devices/cpm/src/jz4740/cpm-jz4740.cc Sun May 13 01:34:16 2018 +0200
85.3 @@ -0,0 +1,73 @@
85.4 +/*
85.5 + * JZ4740 CPM server.
85.6 + *
85.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
85.8 + *
85.9 + * This program is free software; you can redistribute it and/or
85.10 + * modify it under the terms of the GNU General Public License as
85.11 + * published by the Free Software Foundation; either version 2 of
85.12 + * the License, or (at your option) any later version.
85.13 + *
85.14 + * This program is distributed in the hope that it will be useful,
85.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
85.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85.17 + * GNU General Public License for more details.
85.18 + *
85.19 + * You should have received a copy of the GNU General Public License
85.20 + * along with this program; if not, write to the Free Software
85.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
85.22 + * Boston, MA 02110-1301, USA
85.23 + */
85.24 +
85.25 +#include <l4/devices/cpm-jz4740.h>
85.26 +#include <l4/devices/memory.h>
85.27 +#include "cpm-server.h"
85.28 +
85.29 +#include <l4/re/dataspace>
85.30 +#include <l4/re/env>
85.31 +#include <l4/re/util/object_registry>
85.32 +
85.33 +#include <l4/sys/types.h>
85.34 +
85.35 +// Virtual addresses for the CPM and LCD register blocks.
85.36 +
85.37 +static l4_addr_t cpm_virt_base = 0, cpm_virt_base_end = 0;
85.38 +
85.39 +
85.40 +
85.41 +// Access to peripheral memory.
85.42 +
85.43 +static int setup_memory()
85.44 +{
85.45 + if (get_memory("jz4740-cpm", &cpm_virt_base, &cpm_virt_base_end))
85.46 + return 1;
85.47 +
85.48 + return 0;
85.49 +}
85.50 +
85.51 +
85.52 +
85.53 +static L4Re::Util::Registry_server<> server;
85.54 +
85.55 +
85.56 +
85.57 +/* Main program. */
85.58 +
85.59 +int main(void)
85.60 +{
85.61 + if (setup_memory()) return 1;
85.62 +
85.63 + /* Initialise the CPM abstraction. */
85.64 +
85.65 + Cpm_jz4740_chip cpm_device(cpm_virt_base, 12000000);
85.66 +
85.67 + /* Initialise and register a server object. */
85.68 +
85.69 + Cpm_server server_obj(&cpm_device);
85.70 + server.registry()->register_obj(&server_obj, "cpm");
85.71 +
85.72 + /* Enter the IPC server loop. */
85.73 +
85.74 + server.loop();
85.75 + return 0;
85.76 +}
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/pkg/devices/cpm/src/jz4780/Makefile Sun May 13 01:34:16 2018 +0200
86.3 @@ -0,0 +1,13 @@
86.4 +PKGDIR ?= ../../..
86.5 +L4DIR ?= $(PKGDIR)/../..
86.6 +
86.7 +TARGET = dev_cpm_jz4780
86.8 +PC_FILENAME := devices-cpm-jz4780
86.9 +
86.10 +SRC_CC := cpm-jz4780.cc
86.11 +
86.12 +PRIVATE_INCDIR += $(PKGDIR)/cpm/include
86.13 +
86.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-cpm libdevice-cpm-server libdevice-util
86.15 +
86.16 +include $(L4DIR)/mk/prog.mk
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc Sun May 13 01:34:16 2018 +0200
87.3 @@ -0,0 +1,73 @@
87.4 +/*
87.5 + * JZ4780 CPM server.
87.6 + *
87.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
87.8 + *
87.9 + * This program is free software; you can redistribute it and/or
87.10 + * modify it under the terms of the GNU General Public License as
87.11 + * published by the Free Software Foundation; either version 2 of
87.12 + * the License, or (at your option) any later version.
87.13 + *
87.14 + * This program is distributed in the hope that it will be useful,
87.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
87.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87.17 + * GNU General Public License for more details.
87.18 + *
87.19 + * You should have received a copy of the GNU General Public License
87.20 + * along with this program; if not, write to the Free Software
87.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
87.22 + * Boston, MA 02110-1301, USA
87.23 + */
87.24 +
87.25 +#include <l4/devices/cpm-jz4780.h>
87.26 +#include <l4/devices/memory.h>
87.27 +#include "cpm-server.h"
87.28 +
87.29 +#include <l4/re/dataspace>
87.30 +#include <l4/re/env>
87.31 +#include <l4/re/util/object_registry>
87.32 +
87.33 +#include <l4/sys/types.h>
87.34 +
87.35 +// Virtual addresses for the CPM and LCD register blocks.
87.36 +
87.37 +static l4_addr_t cpm_virt_base = 0, cpm_virt_base_end = 0;
87.38 +
87.39 +
87.40 +
87.41 +// Access to peripheral memory.
87.42 +
87.43 +static int setup_memory()
87.44 +{
87.45 + if (get_memory("jz4780-cpm", &cpm_virt_base, &cpm_virt_base_end))
87.46 + return 1;
87.47 +
87.48 + return 0;
87.49 +}
87.50 +
87.51 +
87.52 +
87.53 +static L4Re::Util::Registry_server<> server;
87.54 +
87.55 +
87.56 +
87.57 +/* Main program. */
87.58 +
87.59 +int main(void)
87.60 +{
87.61 + if (setup_memory()) return 1;
87.62 +
87.63 + /* Initialise the CPM abstraction. */
87.64 +
87.65 + Cpm_jz4780_chip cpm_device(cpm_virt_base, 48000000, 32768);
87.66 +
87.67 + /* Initialise and register a server object. */
87.68 +
87.69 + Cpm_server server_obj(&cpm_device);
87.70 + server.registry()->register_obj(&server_obj, "cpm");
87.71 +
87.72 + /* Enter the IPC server loop. */
87.73 +
87.74 + server.loop();
87.75 + return 0;
87.76 +}
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/pkg/devices/cpm/src/server/Makefile Sun May 13 01:34:16 2018 +0200
88.3 @@ -0,0 +1,13 @@
88.4 +PKGDIR ?= ../../..
88.5 +L4DIR ?= $(PKGDIR)/../..
88.6 +
88.7 +TARGET = libdevice_cpm_server.o.a
88.8 +PC_FILENAME := libdevice-cpm-server
88.9 +
88.10 +SRC_CC := cpm-server.cc
88.11 +
88.12 +PRIVATE_INCDIR += $(PKGDIR)/cpm/include
88.13 +
88.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-cpm
88.15 +
88.16 +include $(L4DIR)/mk/lib.mk
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/pkg/devices/cpm/src/server/cpm-server.cc Sun May 13 01:34:16 2018 +0200
89.3 @@ -0,0 +1,69 @@
89.4 +/*
89.5 + * Common CPM server functionality.
89.6 + *
89.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
89.8 + *
89.9 + * This program is free software; you can redistribute it and/or
89.10 + * modify it under the terms of the GNU General Public License as
89.11 + * published by the Free Software Foundation; either version 2 of
89.12 + * the License, or (at your option) any later version.
89.13 + *
89.14 + * This program is distributed in the hope that it will be useful,
89.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
89.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89.17 + * GNU General Public License for more details.
89.18 + *
89.19 + * You should have received a copy of the GNU General Public License
89.20 + * along with this program; if not, write to the Free Software
89.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
89.22 + * Boston, MA 02110-1301, USA
89.23 + */
89.24 +
89.25 +#include "cpm-client.h"
89.26 +#include "cpm-server.h"
89.27 +#include "cpm-ops.h"
89.28 +
89.29 +#include <l4/cxx/ipc_server>
89.30 +#include <l4/re/env>
89.31 +#include <l4/sys/typeinfo_svr>
89.32 +#include <l4/util/util.h>
89.33 +
89.34 +/* Handle invocations. */
89.35 +
89.36 +int
89.37 +Cpm_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
89.38 +{
89.39 + l4_msgtag_t tag;
89.40 +
89.41 + (void) obj;
89.42 + ios >> tag;
89.43 +
89.44 + switch (tag.label())
89.45 + {
89.46 + case L4::Meta::Protocol:
89.47 + return L4::Util::handle_meta_request<Cpm_device_interface>(ios);
89.48 +
89.49 + case Cpm_op_set_lcd_frequencies:
89.50 + uint32_t pclk;
89.51 + int multiplier;
89.52 + ios >> pclk;
89.53 + ios >> multiplier;
89.54 + _chip->set_lcd_frequencies(pclk, multiplier);
89.55 + return L4_EOK;
89.56 +
89.57 + case Cpm_op_start_lcd:
89.58 + _chip->start_lcd();
89.59 + return L4_EOK;
89.60 +
89.61 + case Cpm_op_stop_lcd:
89.62 + _chip->stop_lcd();
89.63 + return L4_EOK;
89.64 +
89.65 + case Cpm_op_update_output_frequency:
89.66 + _chip->update_output_frequency();
89.67 + return L4_EOK;
89.68 +
89.69 + default:
89.70 + return -L4_EBADPROTO;
89.71 + }
89.72 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/pkg/devices/display/Makefile Sun May 13 01:34:16 2018 +0200
90.3 @@ -0,0 +1,8 @@
90.4 +PKGDIR ?= ..
90.5 +L4DIR ?= $(PKGDIR)/../..
90.6 +
90.7 +TARGET := include src
90.8 +
90.9 +include $(L4DIR)/mk/subdir.mk
90.10 +
90.11 +src: include
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/pkg/devices/display/include/Makefile Sun May 13 01:34:16 2018 +0200
91.3 @@ -0,0 +1,6 @@
91.4 +PKGDIR = ../..
91.5 +L4DIR ?= $(PKGDIR)/../..
91.6 +
91.7 +PC_FILENAME := libdevice-display-ops
91.8 +
91.9 +include $(L4DIR)/mk/include.mk
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92.2 +++ b/pkg/devices/display/include/display-client.h Sun May 13 01:34:16 2018 +0200
92.3 @@ -0,0 +1,40 @@
92.4 +/*
92.5 + * Display client to access display servers.
92.6 + *
92.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
92.8 + *
92.9 + * This program is free software; you can redistribute it and/or
92.10 + * modify it under the terms of the GNU General Public License as
92.11 + * published by the Free Software Foundation; either version 2 of
92.12 + * the License, or (at your option) any later version.
92.13 + *
92.14 + * This program is distributed in the hope that it will be useful,
92.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
92.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92.17 + * GNU General Public License for more details.
92.18 + *
92.19 + * You should have received a copy of the GNU General Public License
92.20 + * along with this program; if not, write to the Free Software
92.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
92.22 + * Boston, MA 02110-1301, USA
92.23 + */
92.24 +
92.25 +#pragma once
92.26 +
92.27 +#ifdef __cplusplus
92.28 +
92.29 +#include <l4/re/env>
92.30 +#include "display-ops.h"
92.31 +
92.32 +#include <stdint.h>
92.33 +
92.34 +class Display_device_interface : public L4::Kobject_t<Display_device_interface, L4::Kobject>
92.35 +{
92.36 + L4_KOBJECT(Display_device_interface)
92.37 +
92.38 +public:
92.39 + int disable() throw();
92.40 + int enable() throw();
92.41 +};
92.42 +
92.43 +#endif
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
93.2 +++ b/pkg/devices/display/include/display-ops.h Sun May 13 01:34:16 2018 +0200
93.3 @@ -0,0 +1,24 @@
93.4 +/*
93.5 + * Display server operations.
93.6 + *
93.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
93.8 + *
93.9 + * This program is free software; you can redistribute it and/or
93.10 + * modify it under the terms of the GNU General Public License as
93.11 + * published by the Free Software Foundation; either version 2 of
93.12 + * the License, or (at your option) any later version.
93.13 + *
93.14 + * This program is distributed in the hope that it will be useful,
93.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
93.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93.17 + * GNU General Public License for more details.
93.18 + *
93.19 + * You should have received a copy of the GNU General Public License
93.20 + * along with this program; if not, write to the Free Software
93.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
93.22 + * Boston, MA 02110-1301, USA
93.23 + */
93.24 +
93.25 +#pragma once
93.26 +
93.27 +enum { Display_op_disable, Display_op_enable };
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94.2 +++ b/pkg/devices/display/src/Makefile Sun May 13 01:34:16 2018 +0200
94.3 @@ -0,0 +1,6 @@
94.4 +PKGDIR ?= ../..
94.5 +L4DIR ?= $(PKGDIR)/../..
94.6 +
94.7 +TARGET := client letux400 qi_lb60
94.8 +
94.9 +include $(L4DIR)/mk/subdir.mk
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/pkg/devices/display/src/client/Makefile Sun May 13 01:34:16 2018 +0200
95.3 @@ -0,0 +1,13 @@
95.4 +PKGDIR ?= ../../..
95.5 +L4DIR ?= $(PKGDIR)/../..
95.6 +
95.7 +TARGET = libdevice_display_client.o.a
95.8 +PC_FILENAME := libdevice-display-client
95.9 +
95.10 +SRC_CC := display-client.cc
95.11 +
95.12 +PRIVATE_INCDIR += $(PKGDIR)/display/include
95.13 +
95.14 +REQUIRES_LIBS := l4re_c l4re_c-util
95.15 +
95.16 +include $(L4DIR)/mk/lib.mk
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/pkg/devices/display/src/client/display-client.cc Sun May 13 01:34:16 2018 +0200
96.3 @@ -0,0 +1,44 @@
96.4 +/*
96.5 + * Display client to access display servers.
96.6 + *
96.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
96.8 + *
96.9 + * This program is free software; you can redistribute it and/or
96.10 + * modify it under the terms of the GNU General Public License as
96.11 + * published by the Free Software Foundation; either version 2 of
96.12 + * the License, or (at your option) any later version.
96.13 + *
96.14 + * This program is distributed in the hope that it will be useful,
96.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
96.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96.17 + * GNU General Public License for more details.
96.18 + *
96.19 + * You should have received a copy of the GNU General Public License
96.20 + * along with this program; if not, write to the Free Software
96.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
96.22 + * Boston, MA 02110-1301, USA
96.23 + */
96.24 +
96.25 +#include <l4/cxx/ipc_stream>
96.26 +#include <l4/re/env>
96.27 +#include <l4/sys/err.h>
96.28 +
96.29 +#include "display-client.h"
96.30 +
96.31 +#include <stdint.h>
96.32 +
96.33 +int
96.34 +Display_device_interface::disable() throw()
96.35 +{
96.36 + L4::Ipc::Iostream s(l4_utcb());
96.37 +
96.38 + return l4_error(s.call(cap(), Display_op_disable));
96.39 +}
96.40 +
96.41 +int
96.42 +Display_device_interface::enable() throw()
96.43 +{
96.44 + L4::Ipc::Iostream s(l4_utcb());
96.45 +
96.46 + return l4_error(s.call(cap(), Display_op_enable));
96.47 +}
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
97.2 +++ b/pkg/devices/display/src/letux400/Makefile Sun May 13 01:34:16 2018 +0200
97.3 @@ -0,0 +1,13 @@
97.4 +PKGDIR ?= ../../..
97.5 +L4DIR ?= $(PKGDIR)/../..
97.6 +
97.7 +TARGET = dev_display_letux400
97.8 +PC_FILENAME := devices-display-letux400
97.9 +
97.10 +SRC_CC := display-letux400.cc
97.11 +
97.12 +PRIVATE_INCDIR += $(PKGDIR)/display/include
97.13 +
97.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-backlight-client libdrivers-gpio libdevice-util
97.15 +
97.16 +include $(L4DIR)/mk/prog.mk
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/pkg/devices/display/src/letux400/display-letux400.cc Sun May 13 01:34:16 2018 +0200
98.3 @@ -0,0 +1,162 @@
98.4 +/*
98.5 + * Export Letux 400 display operations as a server.
98.6 + *
98.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
98.8 + *
98.9 + * This program is free software; you can redistribute it and/or
98.10 + * modify it under the terms of the GNU General Public License as
98.11 + * published by the Free Software Foundation; either version 2 of
98.12 + * the License, or (at your option) any later version.
98.13 + *
98.14 + * This program is distributed in the hope that it will be useful,
98.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
98.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
98.17 + * GNU General Public License for more details.
98.18 + *
98.19 + * You should have received a copy of the GNU General Public License
98.20 + * along with this program; if not, write to the Free Software
98.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
98.22 + * Boston, MA 02110-1301, USA
98.23 + */
98.24 +
98.25 +#include <l4/devices/gpio-jz4730.h>
98.26 +#include <l4/devices/backlight-client.h>
98.27 +#include <l4/devices/memory.h>
98.28 +
98.29 +#include <l4/cxx/ipc_server>
98.30 +#include <l4/re/env>
98.31 +#include <l4/re/util/object_registry>
98.32 +#include <l4/sys/capability>
98.33 +
98.34 +#include "display-ops.h"
98.35 +
98.36 +/* Virtual address for the GPIO register block. */
98.37 +
98.38 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
98.39 +
98.40 +/* GPIO and backlight device abstractions. */
98.41 +
98.42 +static Gpio_jz4730_chip *gpio_port_b = 0, *gpio_port_c = 0;
98.43 +static L4::Cap<Backlight_device_interface> backlight_device;
98.44 +
98.45 +
98.46 +
98.47 +/* GPIO pin definitions. */
98.48 +
98.49 +enum Jz4730_lcd_gpio_mask
98.50 +{
98.51 + Jz4730_lcd_gpio_func1 = 0xf8ffff00,
98.52 + Jz4730_lcd_gpio_func2 = 0x07000000,
98.53 +};
98.54 +
98.55 +enum Jz4730_lcd_gpio
98.56 +{
98.57 + Jz4730_lcd_gpio_led_enable = 28,
98.58 + Jz4730_lcd_gpio_display_enable = 29,
98.59 +};
98.60 +
98.61 +
98.62 +
98.63 +static int setup_memory(void)
98.64 +{
98.65 + if (get_memory("jz4730-gpio", &gpio_virt_base, &gpio_virt_base_end))
98.66 + return 1;
98.67 +
98.68 + return 0;
98.69 +}
98.70 +
98.71 +
98.72 +
98.73 +/* Display device. */
98.74 +
98.75 +class Display_device_server : public L4::Server_object_t<L4::Kobject>
98.76 +{
98.77 + Pin_slice lcd_mask1 = {.offset=0, .mask=Jz4730_lcd_gpio_func1};
98.78 + Pin_slice lcd_mask2 = {.offset=0, .mask=Jz4730_lcd_gpio_func2};
98.79 +
98.80 +public:
98.81 + explicit Display_device_server()
98.82 + {
98.83 + /* Set functions for the LCD pins. */
98.84 +
98.85 + gpio_port_b->multi_config_pad(lcd_mask1, Hw::Gpio_chip::Function_alt, 1);
98.86 + gpio_port_b->multi_config_pad(lcd_mask2, Hw::Gpio_chip::Function_alt, 2);
98.87 +
98.88 + /* Enable LED, disable display. */
98.89 +
98.90 + gpio_port_c->setup(Jz4730_lcd_gpio_led_enable, Hw::Gpio_chip::Output, 1);
98.91 + gpio_port_c->setup(Jz4730_lcd_gpio_display_enable, Hw::Gpio_chip::Output, 0);
98.92 + }
98.93 +
98.94 + /* Dispatch incoming requests. */
98.95 +
98.96 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
98.97 + {
98.98 + l4_msgtag_t tag;
98.99 +
98.100 + (void) obj;
98.101 + ios >> tag;
98.102 +
98.103 + switch (tag.label())
98.104 + {
98.105 + case Display_op_disable:
98.106 + disable();
98.107 + return L4_EOK;
98.108 +
98.109 + case Display_op_enable:
98.110 + enable();
98.111 + return L4_EOK;
98.112 +
98.113 + default:
98.114 + return -L4_EBADPROTO;
98.115 + }
98.116 + }
98.117 +
98.118 + /* Switch the display off. */
98.119 +
98.120 + void disable(void)
98.121 + {
98.122 + gpio_port_c->setup(Jz4730_lcd_gpio_display_enable, Hw::Gpio_chip::Output, 0);
98.123 + backlight_device->disable();
98.124 + }
98.125 +
98.126 + /* Switch the display on. */
98.127 +
98.128 + void enable(void)
98.129 + {
98.130 + gpio_port_c->setup(Jz4730_lcd_gpio_display_enable, Hw::Gpio_chip::Output, 1);
98.131 + backlight_device->enable();
98.132 + }
98.133 +};
98.134 +
98.135 +static L4Re::Util::Registry_server<> server;
98.136 +
98.137 +
98.138 +
98.139 +int main(void)
98.140 +{
98.141 + if (setup_memory()) return 1;
98.142 +
98.143 + /* Initialise the GPIO abstractions. */
98.144 +
98.145 + Gpio_jz4730_chip gpb(gpio_virt_base + (1 * 0x30), gpio_virt_base + (2 * 0x30), 32);
98.146 + Gpio_jz4730_chip gpc(gpio_virt_base + (2 * 0x30), gpio_virt_base + (3 * 0x30), 32);
98.147 +
98.148 + gpio_port_b = &gpb;
98.149 + gpio_port_c = &gpc;
98.150 +
98.151 + /* Obtain a reference to the backlight device. */
98.152 +
98.153 + backlight_device = L4Re::Env::env()->get_cap<Backlight_device_interface>("backlight");
98.154 + if (!backlight_device.is_valid()) return 1;
98.155 +
98.156 + /* Initialise and register a new server object. */
98.157 +
98.158 + Display_device_server server_obj;
98.159 + server.registry()->register_obj(&server_obj, "display");
98.160 +
98.161 + /* Enter the IPC server loop. */
98.162 +
98.163 + server.loop();
98.164 + return 0;
98.165 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/pkg/devices/display/src/qi_lb60/Makefile Sun May 13 01:34:16 2018 +0200
99.3 @@ -0,0 +1,13 @@
99.4 +PKGDIR ?= ../../..
99.5 +L4DIR ?= $(PKGDIR)/../..
99.6 +
99.7 +TARGET = dev_display_qi_lb60
99.8 +PC_FILENAME := devices-display-qi_lb60
99.9 +
99.10 +SRC_CC := display-qi_lb60.cc
99.11 +
99.12 +PRIVATE_INCDIR += $(PKGDIR)/display/include
99.13 +
99.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-backlight-client libdrivers-lcd-jz4740 libdrivers-gpio libdevice-util
99.15 +
99.16 +include $(L4DIR)/mk/prog.mk
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
100.2 +++ b/pkg/devices/display/src/qi_lb60/display-qi_lb60.cc Sun May 13 01:34:16 2018 +0200
100.3 @@ -0,0 +1,153 @@
100.4 +/*
100.5 + * Export Ben NanoNote display operations as a server.
100.6 + *
100.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
100.8 + *
100.9 + * This program is free software; you can redistribute it and/or
100.10 + * modify it under the terms of the GNU General Public License as
100.11 + * published by the Free Software Foundation; either version 2 of
100.12 + * the License, or (at your option) any later version.
100.13 + *
100.14 + * This program is distributed in the hope that it will be useful,
100.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
100.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100.17 + * GNU General Public License for more details.
100.18 + *
100.19 + * You should have received a copy of the GNU General Public License
100.20 + * along with this program; if not, write to the Free Software
100.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
100.22 + * Boston, MA 02110-1301, USA
100.23 + */
100.24 +
100.25 +#include <l4/devices/gpio-jz4740.h>
100.26 +#include <l4/devices/backlight-client.h>
100.27 +#include <l4/devices/lcd-jz4740-config.h>
100.28 +#include <l4/devices/lcd-jz4740-panel.h>
100.29 +#include <l4/devices/memory.h>
100.30 +
100.31 +#include <l4/cxx/ipc_server>
100.32 +#include <l4/re/env>
100.33 +#include <l4/re/util/object_registry>
100.34 +#include <l4/sys/capability>
100.35 +
100.36 +#include "display-ops.h"
100.37 +
100.38 +/* Virtual address for the GPIO register block. */
100.39 +
100.40 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
100.41 +
100.42 +/* GPIO and backlight device abstractions. */
100.43 +
100.44 +static Gpio_jz4740_chip *gpio_port_c = 0;
100.45 +static L4::Cap<Backlight_device_interface> backlight_device;
100.46 +
100.47 +
100.48 +
100.49 +/* GPIO pin definitions. */
100.50 +
100.51 +enum Jz4740_lcd_gpio_mask
100.52 +{
100.53 + Jz4740_lcd_gpio_d0_d7 = 0xff,
100.54 +};
100.55 +
100.56 +enum Jz4740_lcd_gpio
100.57 +{
100.58 + Jz4740_lcd_gpio_clk = 18, /* pixel clock */
100.59 + Jz4740_lcd_gpio_rs = 19, /* hsync; command/data select */
100.60 + Jz4740_lcd_gpio_cs = 20, /* vsync; chip select */
100.61 +};
100.62 +
100.63 +
100.64 +
100.65 +static int setup_memory(void)
100.66 +{
100.67 + if (get_memory("jz4740-gpio", &gpio_virt_base, &gpio_virt_base_end))
100.68 + return 1;
100.69 +
100.70 + return 0;
100.71 +}
100.72 +
100.73 +
100.74 +
100.75 +/* Display device. */
100.76 +
100.77 +class Display_device_server : public L4::Server_object_t<L4::Kobject>
100.78 +{
100.79 + Pin_slice slcd8_mask = {.offset=0, .mask=(1 << Jz4740_lcd_gpio_cs) | (1 << Jz4740_lcd_gpio_rs) |
100.80 + (1 << Jz4740_lcd_gpio_clk) | Jz4740_lcd_gpio_d0_d7};
100.81 +
100.82 +public:
100.83 + /* Dispatch incoming requests. */
100.84 +
100.85 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
100.86 + {
100.87 + l4_msgtag_t tag;
100.88 +
100.89 + (void) obj;
100.90 + ios >> tag;
100.91 +
100.92 + switch (tag.label())
100.93 + {
100.94 + case Display_op_disable:
100.95 + disable();
100.96 + return L4_EOK;
100.97 +
100.98 + case Display_op_enable:
100.99 + enable();
100.100 + return L4_EOK;
100.101 +
100.102 + default:
100.103 + return -L4_EBADPROTO;
100.104 + }
100.105 + }
100.106 +
100.107 + /* Switch the display off. */
100.108 +
100.109 + void disable(void)
100.110 + {
100.111 + /* Configure SLCD8 pins. */
100.112 +
100.113 + gpio_port_c->multi_setup(slcd8_mask, Hw::Gpio_chip::Input, 0);
100.114 + backlight_device->disable();
100.115 + }
100.116 +
100.117 + /* Switch the display on. */
100.118 +
100.119 + void enable(void)
100.120 + {
100.121 + /* Configure SLCD8 pins. */
100.122 +
100.123 + gpio_port_c->multi_config_pad(slcd8_mask, Hw::Gpio_chip::Function_alt, 0);
100.124 + backlight_device->enable();
100.125 + }
100.126 +};
100.127 +
100.128 +static L4Re::Util::Registry_server<> server;
100.129 +
100.130 +
100.131 +
100.132 +int main(void)
100.133 +{
100.134 + if (setup_memory()) return 1;
100.135 +
100.136 + /* Initialise the GPIO abstraction. */
100.137 +
100.138 + Gpio_jz4740_chip gpio_port(gpio_virt_base + 0x200, gpio_virt_base + 0x300, 32);
100.139 +
100.140 + gpio_port_c = &gpio_port;
100.141 +
100.142 + /* Obtain a reference to the backlight device. */
100.143 +
100.144 + backlight_device = L4Re::Env::env()->get_cap<Backlight_device_interface>("backlight");
100.145 + if (!backlight_device.is_valid()) return 1;
100.146 +
100.147 + /* Initialise and register a new server object. */
100.148 +
100.149 + Display_device_server server_obj;
100.150 + server.registry()->register_obj(&server_obj, "display");
100.151 +
100.152 + /* Enter the IPC server loop. */
100.153 +
100.154 + server.loop();
100.155 + return 0;
100.156 +}
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101.2 +++ b/pkg/devices/fb/Makefile Sun May 13 01:34:16 2018 +0200
101.3 @@ -0,0 +1,8 @@
101.4 +PKGDIR ?= ..
101.5 +L4DIR ?= $(PKGDIR)/../..
101.6 +
101.7 +TARGET := include src
101.8 +
101.9 +include $(L4DIR)/mk/subdir.mk
101.10 +
101.11 +src: include
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102.2 +++ b/pkg/devices/fb/include/Makefile Sun May 13 01:34:16 2018 +0200
102.3 @@ -0,0 +1,6 @@
102.4 +PKGDIR = ../..
102.5 +L4DIR ?= $(PKGDIR)/../..
102.6 +
102.7 +PC_FILENAME := libdevice-fb-ops
102.8 +
102.9 +include $(L4DIR)/mk/include.mk
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
103.2 +++ b/pkg/devices/fb/include/fb-client.h Sun May 13 01:34:16 2018 +0200
103.3 @@ -0,0 +1,41 @@
103.4 +/*
103.5 + * Framebuffer client to access framebuffer servers.
103.6 + *
103.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
103.8 + *
103.9 + * This program is free software; you can redistribute it and/or
103.10 + * modify it under the terms of the GNU General Public License as
103.11 + * published by the Free Software Foundation; either version 2 of
103.12 + * the License, or (at your option) any later version.
103.13 + *
103.14 + * This program is distributed in the hope that it will be useful,
103.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
103.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103.17 + * GNU General Public License for more details.
103.18 + *
103.19 + * You should have received a copy of the GNU General Public License
103.20 + * along with this program; if not, write to the Free Software
103.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
103.22 + * Boston, MA 02110-1301, USA
103.23 + */
103.24 +
103.25 +#pragma once
103.26 +
103.27 +#ifdef __cplusplus
103.28 +
103.29 +#include <l4/re/dataspace>
103.30 +#include <l4/re/env>
103.31 +#include <l4/re/c/video/view.h>
103.32 +#include <l4/sys/types.h>
103.33 +
103.34 +class Framebuffer_device_interface : public L4::Kobject_t<Framebuffer_device_interface, L4::Kobject>
103.35 +{
103.36 + L4_KOBJECT(Framebuffer_device_interface)
103.37 +
103.38 +public:
103.39 + int get_framebuffer(L4::Cap<L4Re::Dataspace> mem) throw();
103.40 + l4_size_t get_framebuffer_size() throw();
103.41 + int get_view_info(l4re_video_view_info_t *view_info) throw();
103.42 +};
103.43 +
103.44 +#endif
104.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
104.2 +++ b/pkg/devices/fb/include/fb-lcd.h Sun May 13 01:34:16 2018 +0200
104.3 @@ -0,0 +1,50 @@
104.4 +/*
104.5 + * LCD framebuffer server functionality.
104.6 + *
104.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
104.8 + *
104.9 + * This program is free software; you can redistribute it and/or
104.10 + * modify it under the terms of the GNU General Public License as
104.11 + * published by the Free Software Foundation; either version 2 of
104.12 + * the License, or (at your option) any later version.
104.13 + *
104.14 + * This program is distributed in the hope that it will be useful,
104.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
104.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104.17 + * GNU General Public License for more details.
104.18 + *
104.19 + * You should have received a copy of the GNU General Public License
104.20 + * along with this program; if not, write to the Free Software
104.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
104.22 + * Boston, MA 02110-1301, USA
104.23 + */
104.24 +
104.25 +#pragma once
104.26 +
104.27 +#include <l4/devices/lcd-device.h>
104.28 +#include "fb-server.h"
104.29 +
104.30 +#ifdef __cplusplus
104.31 +
104.32 +#include <l4/re/dataspace>
104.33 +#include <l4/sys/capability>
104.34 +
104.35 +class Framebuffer_lcd_server : public Framebuffer_server
104.36 +{
104.37 + Lcd_device *_device;
104.38 +
104.39 +public:
104.40 + explicit Framebuffer_lcd_server(L4::Cap<L4Re::Dataspace> mem, Lcd_device *device)
104.41 + : Framebuffer_server(mem), _device(device)
104.42 + {
104.43 + }
104.44 +
104.45 + l4_size_t get_framebuffer_size();
104.46 + void get_view_info(l4re_video_view_info_t *view_info);
104.47 +};
104.48 +
104.49 +#endif
104.50 +
104.51 +/* Common initiation method. */
104.52 +
104.53 +int run(void);
105.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
105.2 +++ b/pkg/devices/fb/include/fb-ops.h Sun May 13 01:34:16 2018 +0200
105.3 @@ -0,0 +1,28 @@
105.4 +/*
105.5 + * Framebuffer server operations.
105.6 + *
105.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
105.8 + *
105.9 + * This program is free software; you can redistribute it and/or
105.10 + * modify it under the terms of the GNU General Public License as
105.11 + * published by the Free Software Foundation; either version 2 of
105.12 + * the License, or (at your option) any later version.
105.13 + *
105.14 + * This program is distributed in the hope that it will be useful,
105.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
105.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105.17 + * GNU General Public License for more details.
105.18 + *
105.19 + * You should have received a copy of the GNU General Public License
105.20 + * along with this program; if not, write to the Free Software
105.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
105.22 + * Boston, MA 02110-1301, USA
105.23 + */
105.24 +
105.25 +#pragma once
105.26 +
105.27 +enum {
105.28 + Framebuffer_op_get_framebuffer,
105.29 + Framebuffer_op_get_framebuffer_size,
105.30 + Framebuffer_op_get_view_info,
105.31 +};
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
106.2 +++ b/pkg/devices/fb/include/fb-server.h Sun May 13 01:34:16 2018 +0200
106.3 @@ -0,0 +1,54 @@
106.4 +/*
106.5 + * Common framebuffer server functionality.
106.6 + *
106.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
106.8 + *
106.9 + * This program is free software; you can redistribute it and/or
106.10 + * modify it under the terms of the GNU General Public License as
106.11 + * published by the Free Software Foundation; either version 2 of
106.12 + * the License, or (at your option) any later version.
106.13 + *
106.14 + * This program is distributed in the hope that it will be useful,
106.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
106.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
106.17 + * GNU General Public License for more details.
106.18 + *
106.19 + * You should have received a copy of the GNU General Public License
106.20 + * along with this program; if not, write to the Free Software
106.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
106.22 + * Boston, MA 02110-1301, USA
106.23 + */
106.24 +
106.25 +#pragma once
106.26 +
106.27 +#ifdef __cplusplus
106.28 +
106.29 +#include <l4/cxx/ipc_server>
106.30 +#include <l4/re/dataspace>
106.31 +#include <l4/re/env>
106.32 +#include <l4/re/c/video/view.h>
106.33 +#include <l4/sys/types.h>
106.34 +
106.35 +/* Server object to provide framebuffer data access. */
106.36 +
106.37 +class Framebuffer_server : public L4::Server_object_t<L4::Kobject>
106.38 +{
106.39 +private:
106.40 + L4::Cap<L4Re::Dataspace> _mem;
106.41 +
106.42 +public:
106.43 + /* Initialise the server with a capability referencing the exported memory. */
106.44 +
106.45 + explicit Framebuffer_server(L4::Cap<L4Re::Dataspace> mem)
106.46 + : _mem(mem)
106.47 + {}
106.48 +
106.49 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
106.50 +
106.51 + /* Operation methods. */
106.52 +
106.53 + virtual l4_size_t get_framebuffer_size() = 0;
106.54 + virtual void get_view_info(l4re_video_view_info_t *view_info) = 0;
106.55 +};
106.56 +
106.57 +#endif
107.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
107.2 +++ b/pkg/devices/fb/src/Makefile Sun May 13 01:34:16 2018 +0200
107.3 @@ -0,0 +1,9 @@
107.4 +PKGDIR ?= ../..
107.5 +L4DIR ?= $(PKGDIR)/../..
107.6 +
107.7 +TARGET := client jz4740 lcd server
107.8 +
107.9 +include $(L4DIR)/mk/subdir.mk
107.10 +
107.11 +jz4740: lcd
107.12 +lcd: server
108.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
108.2 +++ b/pkg/devices/fb/src/client/Makefile Sun May 13 01:34:16 2018 +0200
108.3 @@ -0,0 +1,13 @@
108.4 +PKGDIR ?= ../../..
108.5 +L4DIR ?= $(PKGDIR)/../..
108.6 +
108.7 +TARGET = libdevice_fb_client.o.a
108.8 +PC_FILENAME := libdevice-fb-client
108.9 +
108.10 +SRC_CC := fb-client.cc
108.11 +
108.12 +PRIVATE_INCDIR += $(PKGDIR)/fb/include
108.13 +
108.14 +REQUIRES_LIBS := l4re_c l4re_c-util
108.15 +
108.16 +include $(L4DIR)/mk/lib.mk
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109.2 +++ b/pkg/devices/fb/src/client/fb-client.cc Sun May 13 01:34:16 2018 +0200
109.3 @@ -0,0 +1,72 @@
109.4 +/*
109.5 + * Framebuffer client to access framebuffer servers.
109.6 + *
109.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
109.8 + *
109.9 + * This program is free software; you can redistribute it and/or
109.10 + * modify it under the terms of the GNU General Public License as
109.11 + * published by the Free Software Foundation; either version 2 of
109.12 + * the License, or (at your option) any later version.
109.13 + *
109.14 + * This program is distributed in the hope that it will be useful,
109.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
109.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109.17 + * GNU General Public License for more details.
109.18 + *
109.19 + * You should have received a copy of the GNU General Public License
109.20 + * along with this program; if not, write to the Free Software
109.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
109.22 + * Boston, MA 02110-1301, USA
109.23 + */
109.24 +
109.25 +#include "fb-client.h"
109.26 +#include "fb-ops.h"
109.27 +
109.28 +#include <l4/cxx/ipc_stream>
109.29 +#include <l4/re/env>
109.30 +
109.31 +#include <stdint.h>
109.32 +
109.33 +int
109.34 +Framebuffer_device_interface::get_framebuffer(L4::Cap<L4Re::Dataspace> mem) throw()
109.35 +{
109.36 + L4::Ipc::Iostream s(l4_utcb());
109.37 +
109.38 + /* Send a "receive item" for requesting a capability. */
109.39 +
109.40 + s << L4::Ipc::Small_buf(mem);
109.41 +
109.42 + return l4_error(s.call(cap(), Framebuffer_op_get_framebuffer));
109.43 +}
109.44 +
109.45 +l4_size_t
109.46 +Framebuffer_device_interface::get_framebuffer_size() throw()
109.47 +{
109.48 + L4::Ipc::Iostream s(l4_utcb());
109.49 + l4_size_t size;
109.50 +
109.51 + /* Return zero on failure. */
109.52 +
109.53 + if (l4_error(s.call(cap(), Framebuffer_op_get_framebuffer_size)))
109.54 + return 0;
109.55 +
109.56 + s >> size;
109.57 + return size;
109.58 +}
109.59 +
109.60 +int
109.61 +Framebuffer_device_interface::get_view_info(l4re_video_view_info_t *view_info) throw()
109.62 +{
109.63 + L4::Ipc::Iostream s(l4_utcb());
109.64 +
109.65 + int err = l4_error(s.call(cap(), Framebuffer_op_get_view_info));
109.66 + if (err) return err;
109.67 +
109.68 + unsigned long expected = sizeof(*view_info);
109.69 + unsigned long size = expected;
109.70 +
109.71 + s >> L4::Ipc::buf_cp_in<uint8_t>((uint8_t *) view_info, expected);
109.72 +
109.73 + if (size != expected) return -L4_EIO;
109.74 + return L4_EOK;
109.75 +}
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
110.2 +++ b/pkg/devices/fb/src/jz4740/Makefile Sun May 13 01:34:16 2018 +0200
110.3 @@ -0,0 +1,13 @@
110.4 +PKGDIR ?= ../../..
110.5 +L4DIR ?= $(PKGDIR)/../..
110.6 +
110.7 +TARGET = dev_fb_jz4740
110.8 +PC_FILENAME := devices-fb-jz4740
110.9 +
110.10 +SRC_CC := fb-jz4740.cc
110.11 +
110.12 +PRIVATE_INCDIR += $(PKGDIR)/fb/include
110.13 +
110.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-fb-lcd libdevice-lcd-jz4740
110.15 +
110.16 +include $(L4DIR)/mk/prog.mk
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
111.2 +++ b/pkg/devices/fb/src/jz4740/fb-jz4740.cc Sun May 13 01:34:16 2018 +0200
111.3 @@ -0,0 +1,29 @@
111.4 +/*
111.5 + * Export the framebuffer for the Ben NanoNote via the "fb" capability.
111.6 + *
111.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
111.8 + *
111.9 + * This program is free software; you can redistribute it and/or
111.10 + * modify it under the terms of the GNU General Public License as
111.11 + * published by the Free Software Foundation; either version 2 of
111.12 + * the License, or (at your option) any later version.
111.13 + *
111.14 + * This program is distributed in the hope that it will be useful,
111.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
111.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
111.17 + * GNU General Public License for more details.
111.18 + *
111.19 + * You should have received a copy of the GNU General Public License
111.20 + * along with this program; if not, write to the Free Software
111.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
111.22 + * Boston, MA 02110-1301, USA
111.23 + */
111.24 +
111.25 +#include "fb-lcd.h"
111.26 +
111.27 +/* Main program. */
111.28 +
111.29 +int main()
111.30 +{
111.31 + return run();
111.32 +}
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
112.2 +++ b/pkg/devices/fb/src/lcd/Makefile Sun May 13 01:34:16 2018 +0200
112.3 @@ -0,0 +1,13 @@
112.4 +PKGDIR ?= ../../..
112.5 +L4DIR ?= $(PKGDIR)/../..
112.6 +
112.7 +TARGET = libdevice_fb_lcd.o.a
112.8 +PC_FILENAME := libdevice-fb-lcd
112.9 +
112.10 +SRC_CC := fb-lcd.cc
112.11 +
112.12 +PRIVATE_INCDIR += $(PKGDIR)/fb/include
112.13 +
112.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-fb-server libdevice-lcd
112.15 +
112.16 +include $(L4DIR)/mk/lib.mk
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
113.2 +++ b/pkg/devices/fb/src/lcd/fb-lcd.cc Sun May 13 01:34:16 2018 +0200
113.3 @@ -0,0 +1,80 @@
113.4 +/*
113.5 + * Export the framebuffer as a data space accessible via the "fb" capability.
113.6 + *
113.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
113.8 + *
113.9 + * This program is free software; you can redistribute it and/or
113.10 + * modify it under the terms of the GNU General Public License as
113.11 + * published by the Free Software Foundation; either version 2 of
113.12 + * the License, or (at your option) any later version.
113.13 + *
113.14 + * This program is distributed in the hope that it will be useful,
113.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
113.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
113.17 + * GNU General Public License for more details.
113.18 + *
113.19 + * You should have received a copy of the GNU General Public License
113.20 + * along with this program; if not, write to the Free Software
113.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
113.22 + * Boston, MA 02110-1301, USA
113.23 + */
113.24 +
113.25 +#include <l4/devices/lcd-device.h>
113.26 +#include "fb-lcd.h"
113.27 +#include "fb-server.h"
113.28 +
113.29 +#include <l4/cxx/ipc_stream>
113.30 +#include <l4/re/dataspace>
113.31 +#include <l4/re/env>
113.32 +#include <l4/re/util/object_registry>
113.33 +
113.34 +
113.35 +
113.36 +// Device-specific methods.
113.37 +
113.38 +l4_size_t
113.39 +Framebuffer_lcd_server::get_framebuffer_size()
113.40 +{
113.41 + return _device->get_framebuffer_size();
113.42 +}
113.43 +
113.44 +void
113.45 +Framebuffer_lcd_server::get_view_info(l4re_video_view_info_t *view_info)
113.46 +{
113.47 + _device->get_view_info(view_info);
113.48 +}
113.49 +
113.50 +
113.51 +
113.52 +static L4Re::Util::Registry_server<> server;
113.53 +
113.54 +
113.55 +
113.56 +// Main program.
113.57 +
113.58 +int run()
113.59 +{
113.60 + // Obtain the LCD device.
113.61 +
113.62 + Lcd_device *lcd_device = Lcd_device::get_device();
113.63 +
113.64 + // Memory allocation capability for the framebuffer data.
113.65 +
113.66 + L4::Cap<L4Re::Dataspace> mem = lcd_device->get_framebuffer_cap();
113.67 +
113.68 + if (!mem.is_valid()) return 1;
113.69 +
113.70 + // Enable the LCD device.
113.71 +
113.72 + lcd_device->enable();
113.73 +
113.74 + // Initialise and register a server object.
113.75 +
113.76 + Framebuffer_lcd_server server_obj(mem, lcd_device);
113.77 + server.registry()->register_obj(&server_obj, "fb");
113.78 +
113.79 + // Enter the IPC server loop.
113.80 +
113.81 + server.loop();
113.82 + return 0;
113.83 +}
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
114.2 +++ b/pkg/devices/fb/src/server/Makefile Sun May 13 01:34:16 2018 +0200
114.3 @@ -0,0 +1,13 @@
114.4 +PKGDIR ?= ../../..
114.5 +L4DIR ?= $(PKGDIR)/../..
114.6 +
114.7 +TARGET = libdevice_fb_server.o.a
114.8 +PC_FILENAME := libdevice-fb-server
114.9 +
114.10 +SRC_CC := fb-server.cc
114.11 +
114.12 +PRIVATE_INCDIR += $(PKGDIR)/fb/include
114.13 +
114.14 +REQUIRES_LIBS := l4re_c l4re_c-util
114.15 +
114.16 +include $(L4DIR)/mk/lib.mk
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
115.2 +++ b/pkg/devices/fb/src/server/fb-server.cc Sun May 13 01:34:16 2018 +0200
115.3 @@ -0,0 +1,68 @@
115.4 +/*
115.5 + * Common framebuffer server functionality.
115.6 + *
115.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
115.8 + *
115.9 + * This program is free software; you can redistribute it and/or
115.10 + * modify it under the terms of the GNU General Public License as
115.11 + * published by the Free Software Foundation; either version 2 of
115.12 + * the License, or (at your option) any later version.
115.13 + *
115.14 + * This program is distributed in the hope that it will be useful,
115.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
115.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
115.17 + * GNU General Public License for more details.
115.18 + *
115.19 + * You should have received a copy of the GNU General Public License
115.20 + * along with this program; if not, write to the Free Software
115.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
115.22 + * Boston, MA 02110-1301, USA
115.23 + */
115.24 +
115.25 +#include "fb-client.h"
115.26 +#include "fb-server.h"
115.27 +#include "fb-ops.h"
115.28 +
115.29 +#include <l4/cxx/ipc_server>
115.30 +#include <l4/re/env>
115.31 +#include <l4/sys/typeinfo_svr>
115.32 +#include <l4/util/util.h>
115.33 +
115.34 +#include <stdint.h>
115.35 +
115.36 +/* Handle invocations. */
115.37 +
115.38 +int
115.39 +Framebuffer_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
115.40 +{
115.41 + l4_msgtag_t tag;
115.42 +
115.43 + (void) obj;
115.44 + ios >> tag;
115.45 +
115.46 + switch (tag.label())
115.47 + {
115.48 + case L4::Meta::Protocol:
115.49 + return L4::Util::handle_meta_request<Framebuffer_device_interface>(ios);
115.50 +
115.51 + case Framebuffer_op_get_framebuffer:
115.52 + ios << _mem;
115.53 + return L4_EOK;
115.54 +
115.55 + case Framebuffer_op_get_framebuffer_size:
115.56 + ios << get_framebuffer_size();
115.57 + return L4_EOK;
115.58 +
115.59 + case Framebuffer_op_get_view_info:
115.60 + l4re_video_view_info_t view_info;
115.61 + get_view_info(&view_info);
115.62 +
115.63 + /* Serialise the view information structure. */
115.64 +
115.65 + ios << L4::Ipc::buf_cp_out<uint8_t>((uint8_t *) &view_info, sizeof(view_info));
115.66 + return L4_EOK;
115.67 +
115.68 + default:
115.69 + return -L4_EBADPROTO;
115.70 + }
115.71 +}
116.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
116.2 +++ b/pkg/devices/input/Makefile Sun May 13 01:34:16 2018 +0200
116.3 @@ -0,0 +1,8 @@
116.4 +PKGDIR ?= ..
116.5 +L4DIR ?= $(PKGDIR)/../..
116.6 +
116.7 +TARGET := include src
116.8 +
116.9 +include $(L4DIR)/mk/subdir.mk
116.10 +
116.11 +src: include
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
117.2 +++ b/pkg/devices/input/include/Makefile Sun May 13 01:34:16 2018 +0200
117.3 @@ -0,0 +1,6 @@
117.4 +PKGDIR = ../..
117.5 +L4DIR ?= $(PKGDIR)/../..
117.6 +
117.7 +PC_FILENAME := libdevice-input-ops
117.8 +
117.9 +include $(L4DIR)/mk/include.mk
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
118.2 +++ b/pkg/devices/input/include/input-keypad-client.h Sun May 13 01:34:16 2018 +0200
118.3 @@ -0,0 +1,108 @@
118.4 +/*
118.5 + * Common keypad client functionality for input event generation.
118.6 + *
118.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
118.8 + *
118.9 + * This program is free software; you can redistribute it and/or
118.10 + * modify it under the terms of the GNU General Public License as
118.11 + * published by the Free Software Foundation; either version 2 of
118.12 + * the License, or (at your option) any later version.
118.13 + *
118.14 + * This program is distributed in the hope that it will be useful,
118.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
118.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118.17 + * GNU General Public License for more details.
118.18 + *
118.19 + * You should have received a copy of the GNU General Public License
118.20 + * along with this program; if not, write to the Free Software
118.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
118.22 + * Boston, MA 02110-1301, USA
118.23 + */
118.24 +
118.25 +#pragma once
118.26 +
118.27 +#include <l4/devices/keypad.h>
118.28 +#include <l4/devices/keypad-client.h>
118.29 +
118.30 +#include <pthread.h>
118.31 +#include <pthread-l4.h>
118.32 +
118.33 +#include <l4/re/event_enums.h>
118.34 +
118.35 +#include <stdint.h>
118.36 +
118.37 +/* Input event and handler. */
118.38 +
118.39 +typedef struct
118.40 +{
118.41 + enum L4Re_events_ev type;
118.42 + int code;
118.43 + int value;
118.44 +} Input_event;
118.45 +
118.46 +typedef void (*Input_handler)(Input_event, void *);
118.47 +
118.48 +
118.49 +
118.50 +#ifdef __cplusplus
118.51 +
118.52 +#include <l4/re/dataspace>
118.53 +#include <l4/re/env>
118.54 +
118.55 +/* Client object to provide input event access. */
118.56 +
118.57 +class Input_keypad_client
118.58 +{
118.59 + /* Memory and keypad access capabilities. */
118.60 +
118.61 + L4::Cap<L4Re::Dataspace> _mem;
118.62 + L4::Cap<Keypad_device_interface> _keypad_server;
118.63 +
118.64 + /* Keypad layout details. */
118.65 +
118.66 + Keypad *_keypad;
118.67 +
118.68 + /* Keypad memory. */
118.69 +
118.70 + void *_keymem = 0, *_keymem_previous = 0;
118.71 +
118.72 + /* Input framework integration. */
118.73 +
118.74 + Input_handler _handler = 0;
118.75 +
118.76 + /* Thread details. */
118.77 +
118.78 + pthread_t _pthread;
118.79 + void *_priv;
118.80 +
118.81 + /* Initialisation functions. */
118.82 +
118.83 + void init_memory();
118.84 + void init_keypad();
118.85 + void init_keypad_data();
118.86 + void release_keypad_data();
118.87 +
118.88 + /* Activity methods. */
118.89 +
118.90 + static void *scan_mainloop(void *data);
118.91 + void scan_keypad();
118.92 +
118.93 +public:
118.94 + explicit Input_keypad_client(Keypad *keypad) : _keypad(keypad)
118.95 + {
118.96 + init_memory();
118.97 + init_keypad();
118.98 + init_keypad_data();
118.99 + }
118.100 +
118.101 + ~Input_keypad_client()
118.102 + {
118.103 + release_keypad_data();
118.104 + }
118.105 +
118.106 + /* Thread initialisation. */
118.107 +
118.108 + void attach(Input_handler handler, void *priv);
118.109 +};
118.110 +
118.111 +#endif
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
119.2 +++ b/pkg/devices/input/src/Makefile Sun May 13 01:34:16 2018 +0200
119.3 @@ -0,0 +1,6 @@
119.4 +PKGDIR ?= ../..
119.5 +L4DIR ?= $(PKGDIR)/../..
119.6 +
119.7 +TARGET := keypad
119.8 +
119.9 +include $(L4DIR)/mk/subdir.mk
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
120.2 +++ b/pkg/devices/input/src/keypad/Makefile Sun May 13 01:34:16 2018 +0200
120.3 @@ -0,0 +1,13 @@
120.4 +PKGDIR ?= ../../..
120.5 +L4DIR ?= $(PKGDIR)/../..
120.6 +
120.7 +TARGET = libinput_keypad.o.a
120.8 +PC_FILENAME := libdevice-input-keypad
120.9 +
120.10 +SRC_CC := input-keypad-client.cc
120.11 +
120.12 +PRIVATE_INCDIR += $(PKGDIR)/input/include
120.13 +
120.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-keypad-client libdrivers-keypad
120.15 +
120.16 +include $(L4DIR)/mk/lib.mk
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
121.2 +++ b/pkg/devices/input/src/keypad/input-keypad-client.cc Sun May 13 01:34:16 2018 +0200
121.3 @@ -0,0 +1,191 @@
121.4 +/*
121.5 + * Common keypad client functionality for input event generation.
121.6 + *
121.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
121.8 + *
121.9 + * This program is free software; you can redistribute it and/or
121.10 + * modify it under the terms of the GNU General Public License as
121.11 + * published by the Free Software Foundation; either version 2 of
121.12 + * the License, or (at your option) any later version.
121.13 + *
121.14 + * This program is distributed in the hope that it will be useful,
121.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
121.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
121.17 + * GNU General Public License for more details.
121.18 + *
121.19 + * You should have received a copy of the GNU General Public License
121.20 + * along with this program; if not, write to the Free Software
121.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
121.22 + * Boston, MA 02110-1301, USA
121.23 + */
121.24 +
121.25 +#include <l4/devices/input-keypad-client.h>
121.26 +
121.27 +#include <pthread.h>
121.28 +#include <pthread-l4.h>
121.29 +
121.30 +#include <l4/re/dataspace>
121.31 +#include <l4/re/env>
121.32 +#include <l4/re/rm>
121.33 +#include <l4/re/util/cap_alloc>
121.34 +
121.35 +#include <l4/re/event_enums.h>
121.36 +#include <l4/sys/thread.h>
121.37 +#include <l4/util/util.h>
121.38 +
121.39 +#include <stdlib.h>
121.40 +
121.41 +/* Obtain a capability for the keypad data. */
121.42 +
121.43 +void
121.44 +Input_keypad_client::init_memory()
121.45 +{
121.46 + _mem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
121.47 +}
121.48 +
121.49 +/* Obtain a reference to the keypad. */
121.50 +
121.51 +void
121.52 +Input_keypad_client::init_keypad()
121.53 +{
121.54 + _keypad_server = L4Re::Env::env()->get_cap<Keypad_device_interface>("keypad");
121.55 +}
121.56 +
121.57 +/* Access the keypad server memory. */
121.58 +
121.59 +void
121.60 +Input_keypad_client::init_keypad_data()
121.61 +{
121.62 + if (!_mem.is_valid())
121.63 + return;
121.64 +
121.65 + if (!_keypad_server.is_valid())
121.66 + return;
121.67 +
121.68 + /* Obtain a reference to the keypad data. */
121.69 +
121.70 + if (_keypad_server->get_keypad_data(_mem))
121.71 + return;
121.72 +
121.73 + /* Attach the keypad data to a region in this task. */
121.74 +
121.75 + if (L4Re::Env::env()->rm()->attach(&_keymem, _mem->size(),
121.76 + L4Re::Rm::Search_addr,
121.77 + L4::Ipc::make_cap_rw(_mem)))
121.78 + return;
121.79 +
121.80 + /* Allocate memory for a copy of the keypad data. */
121.81 +
121.82 + _keymem_previous = malloc(_mem->size());
121.83 +}
121.84 +
121.85 +/* Release capabilities and the memory for a copy of the keypad data. */
121.86 +
121.87 +void
121.88 +Input_keypad_client::release_keypad_data()
121.89 +{
121.90 + if (_mem.is_valid())
121.91 + L4Re::Util::cap_alloc.free(_mem);
121.92 +
121.93 + if (_keypad_server.is_valid())
121.94 + L4Re::Util::cap_alloc.free(_keypad_server);
121.95 +
121.96 + if (_keymem_previous && (_keymem_previous != NULL))
121.97 + free(_keymem_previous);
121.98 +}
121.99 +
121.100 +/* Scan the keypad, compare old and new states, and generate key events. */
121.101 +
121.102 +void
121.103 +Input_keypad_client::scan_keypad()
121.104 +{
121.105 + uint32_t *keymem = (uint32_t *) _keymem;
121.106 + uint32_t *keymem_previous = (uint32_t *) _keymem_previous;
121.107 + int row, column, key_pressed;
121.108 + uint32_t changed, mask;
121.109 + Input_event event;
121.110 +
121.111 + for (column = 0; column < _keypad->columns(); column++)
121.112 + {
121.113 + /* Test for differences within each column. */
121.114 +
121.115 + changed = keymem[column] ^ keymem_previous[column];
121.116 +
121.117 + /* Transfer the current values to the previous values once used. */
121.118 +
121.119 + keymem_previous[column] = keymem[column];
121.120 +
121.121 + /* Move to the next column if no changes occurred. */
121.122 +
121.123 + if (!changed) continue;
121.124 +
121.125 + /* Inspect each changed row position. */
121.126 +
121.127 + mask = 1 << (_keypad->rows() - 1);
121.128 +
121.129 + for (row = 0; row < _keypad->rows(); row++)
121.130 + {
121.131 + if (changed & mask)
121.132 + {
121.133 + key_pressed = keymem[column] & mask;
121.134 +
121.135 + /* Construct an event using the appropriate key code. */
121.136 +
121.137 + event = (Input_event) {
121.138 + L4RE_EV_KEY, _keypad->code(column, row), key_pressed
121.139 + };
121.140 +
121.141 + /* Invoke the supplied handler. */
121.142 +
121.143 + _handler(event, _priv);
121.144 + }
121.145 + mask >>= 1;
121.146 + }
121.147 + }
121.148 +}
121.149 +
121.150 +/* Perform keypad scanning in a separate thread. */
121.151 +
121.152 +void *
121.153 +Input_keypad_client::scan_mainloop(void *data)
121.154 +{
121.155 + /* Since this is a static method, obtain instance details from the data. */
121.156 +
121.157 + Input_keypad_client *self = reinterpret_cast<Input_keypad_client *>(data);
121.158 +
121.159 + while (1)
121.160 + {
121.161 + if (self->_handler) self->scan_keypad();
121.162 + l4_sleep(20); /* 20ms -> 50Hz */
121.163 + }
121.164 +
121.165 + return 0;
121.166 +}
121.167 +
121.168 +/* Thread initialisation for the keypad scanning activity. */
121.169 +
121.170 +void
121.171 +Input_keypad_client::attach(Input_handler handler, void *priv)
121.172 +{
121.173 + pthread_attr_t thread_attr;
121.174 + struct sched_param sp;
121.175 +
121.176 + /* Record the handler and bundled private data. */
121.177 +
121.178 + _handler = handler;
121.179 + _priv = priv;
121.180 +
121.181 + /* Thread initialisation boilerplate. */
121.182 +
121.183 + if (pthread_attr_init(&thread_attr))
121.184 + return;
121.185 +
121.186 + sp.sched_priority = 0x20;
121.187 + pthread_attr_setschedparam(&thread_attr, &sp);
121.188 + pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
121.189 + pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
121.190 +
121.191 + /* Provide this instance as the private data. */
121.192 +
121.193 + pthread_create(&_pthread, &thread_attr, scan_mainloop, this);
121.194 +}
122.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
122.2 +++ b/pkg/devices/keypad/Makefile Sun May 13 01:34:16 2018 +0200
122.3 @@ -0,0 +1,8 @@
122.4 +PKGDIR ?= ..
122.5 +L4DIR ?= $(PKGDIR)/../..
122.6 +
122.7 +TARGET := include src
122.8 +
122.9 +include $(L4DIR)/mk/subdir.mk
122.10 +
122.11 +src: include
123.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
123.2 +++ b/pkg/devices/keypad/include/Makefile Sun May 13 01:34:16 2018 +0200
123.3 @@ -0,0 +1,6 @@
123.4 +PKGDIR = ../..
123.5 +L4DIR ?= $(PKGDIR)/../..
123.6 +
123.7 +PC_FILENAME := libdevice-keypad-ops
123.8 +
123.9 +include $(L4DIR)/mk/include.mk
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
124.2 +++ b/pkg/devices/keypad/include/keypad-client.h Sun May 13 01:34:16 2018 +0200
124.3 @@ -0,0 +1,38 @@
124.4 +/*
124.5 + * Keypad client to access keypad servers.
124.6 + *
124.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
124.8 + *
124.9 + * This program is free software; you can redistribute it and/or
124.10 + * modify it under the terms of the GNU General Public License as
124.11 + * published by the Free Software Foundation; either version 2 of
124.12 + * the License, or (at your option) any later version.
124.13 + *
124.14 + * This program is distributed in the hope that it will be useful,
124.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
124.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
124.17 + * GNU General Public License for more details.
124.18 + *
124.19 + * You should have received a copy of the GNU General Public License
124.20 + * along with this program; if not, write to the Free Software
124.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
124.22 + * Boston, MA 02110-1301, USA
124.23 + */
124.24 +
124.25 +#pragma once
124.26 +
124.27 +#ifdef __cplusplus
124.28 +
124.29 +#include <l4/re/dataspace>
124.30 +#include <l4/re/env>
124.31 +#include "keypad-ops.h"
124.32 +
124.33 +class Keypad_device_interface : public L4::Kobject_t<Keypad_device_interface, L4::Kobject>
124.34 +{
124.35 + L4_KOBJECT(Keypad_device_interface)
124.36 +
124.37 +public:
124.38 + int get_keypad_data(L4::Cap<L4Re::Dataspace> mem) throw();
124.39 +};
124.40 +
124.41 +#endif
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125.2 +++ b/pkg/devices/keypad/include/keypad-ops.h Sun May 13 01:34:16 2018 +0200
125.3 @@ -0,0 +1,24 @@
125.4 +/*
125.5 + * Keypad server operations.
125.6 + *
125.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
125.8 + *
125.9 + * This program is free software; you can redistribute it and/or
125.10 + * modify it under the terms of the GNU General Public License as
125.11 + * published by the Free Software Foundation; either version 2 of
125.12 + * the License, or (at your option) any later version.
125.13 + *
125.14 + * This program is distributed in the hope that it will be useful,
125.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
125.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
125.17 + * GNU General Public License for more details.
125.18 + *
125.19 + * You should have received a copy of the GNU General Public License
125.20 + * along with this program; if not, write to the Free Software
125.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
125.22 + * Boston, MA 02110-1301, USA
125.23 + */
125.24 +
125.25 +#pragma once
125.26 +
125.27 +enum { Keypad_op_get_keypad_data };
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126.2 +++ b/pkg/devices/keypad/include/keypad-server.h Sun May 13 01:34:16 2018 +0200
126.3 @@ -0,0 +1,47 @@
126.4 +/*
126.5 + * Common keypad server functionality.
126.6 + *
126.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
126.8 + *
126.9 + * This program is free software; you can redistribute it and/or
126.10 + * modify it under the terms of the GNU General Public License as
126.11 + * published by the Free Software Foundation; either version 2 of
126.12 + * the License, or (at your option) any later version.
126.13 + *
126.14 + * This program is distributed in the hope that it will be useful,
126.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
126.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
126.17 + * GNU General Public License for more details.
126.18 + *
126.19 + * You should have received a copy of the GNU General Public License
126.20 + * along with this program; if not, write to the Free Software
126.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
126.22 + * Boston, MA 02110-1301, USA
126.23 + */
126.24 +
126.25 +#pragma once
126.26 +
126.27 +#include <l4/cxx/ipc_server>
126.28 +#include <l4/re/dataspace>
126.29 +#include <l4/re/env>
126.30 +
126.31 +#ifdef __cplusplus
126.32 +
126.33 +/* Server object to provide keypad data access. */
126.34 +
126.35 +class Keypad_server : public L4::Server_object_t<L4::Kobject>
126.36 +{
126.37 +private:
126.38 + L4::Cap<L4Re::Dataspace> _mem;
126.39 +
126.40 +public:
126.41 + /* Initialise the server with a capability referencing the exported memory. */
126.42 +
126.43 + explicit Keypad_server(L4::Cap<L4Re::Dataspace> mem)
126.44 + : _mem(mem)
126.45 + {}
126.46 +
126.47 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
126.48 +};
126.49 +
126.50 +#endif
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
127.2 +++ b/pkg/devices/keypad/src/Makefile Sun May 13 01:34:16 2018 +0200
127.3 @@ -0,0 +1,9 @@
127.4 +PKGDIR ?= ../..
127.5 +L4DIR ?= $(PKGDIR)/../..
127.6 +
127.7 +TARGET := client letux400 qi_lb60 server
127.8 +
127.9 +include $(L4DIR)/mk/subdir.mk
127.10 +
127.11 +letux400: server
127.12 +qi_lb60: server
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
128.2 +++ b/pkg/devices/keypad/src/client/Makefile Sun May 13 01:34:16 2018 +0200
128.3 @@ -0,0 +1,13 @@
128.4 +PKGDIR ?= ../../..
128.5 +L4DIR ?= $(PKGDIR)/../..
128.6 +
128.7 +TARGET = libdevice_keypad_client.o.a
128.8 +PC_FILENAME := libdevice-keypad-client
128.9 +
128.10 +SRC_CC := keypad-client.cc
128.11 +
128.12 +PRIVATE_INCDIR += $(PKGDIR)/keypad/include
128.13 +
128.14 +REQUIRES_LIBS := l4re_c l4re_c-util
128.15 +
128.16 +include $(L4DIR)/mk/lib.mk
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
129.2 +++ b/pkg/devices/keypad/src/client/keypad-client.cc Sun May 13 01:34:16 2018 +0200
129.3 @@ -0,0 +1,37 @@
129.4 +/*
129.5 + * Keypad client to access keypad servers.
129.6 + *
129.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
129.8 + *
129.9 + * This program is free software; you can redistribute it and/or
129.10 + * modify it under the terms of the GNU General Public License as
129.11 + * published by the Free Software Foundation; either version 2 of
129.12 + * the License, or (at your option) any later version.
129.13 + *
129.14 + * This program is distributed in the hope that it will be useful,
129.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
129.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129.17 + * GNU General Public License for more details.
129.18 + *
129.19 + * You should have received a copy of the GNU General Public License
129.20 + * along with this program; if not, write to the Free Software
129.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
129.22 + * Boston, MA 02110-1301, USA
129.23 + */
129.24 +
129.25 +#include <l4/cxx/ipc_stream>
129.26 +#include <l4/re/env>
129.27 +
129.28 +#include "keypad-client.h"
129.29 +
129.30 +int
129.31 +Keypad_device_interface::get_keypad_data(L4::Cap<L4Re::Dataspace> mem) throw()
129.32 +{
129.33 + L4::Ipc::Iostream s(l4_utcb());
129.34 +
129.35 + /* Send a "receive item" for requesting a capability. */
129.36 +
129.37 + s << L4::Ipc::Small_buf(mem);
129.38 +
129.39 + return l4_error(s.call(cap(), Keypad_op_get_keypad_data));
129.40 +}
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
130.2 +++ b/pkg/devices/keypad/src/letux400/Makefile Sun May 13 01:34:16 2018 +0200
130.3 @@ -0,0 +1,13 @@
130.4 +PKGDIR ?= ../../..
130.5 +L4DIR ?= $(PKGDIR)/../..
130.6 +
130.7 +TARGET = dev_keypad_letux400
130.8 +PC_FILENAME := devices-keypad-letux400
130.9 +
130.10 +SRC_CC := keypad-letux400.cc
130.11 +
130.12 +PRIVATE_INCDIR += $(PKGDIR)/keypad/include
130.13 +
130.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-gpio libdevice-util libdevice-keypad-server
130.15 +
130.16 +include $(L4DIR)/mk/prog.mk
131.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
131.2 +++ b/pkg/devices/keypad/src/letux400/keypad-letux400.cc Sun May 13 01:34:16 2018 +0200
131.3 @@ -0,0 +1,213 @@
131.4 +/*
131.5 + * Export the keypad GPIOs on the Letux 400 as a data space accessible via the
131.6 + * "keypad" capability.
131.7 + *
131.8 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
131.9 + *
131.10 + * This program is free software; you can redistribute it and/or
131.11 + * modify it under the terms of the GNU General Public License as
131.12 + * published by the Free Software Foundation; either version 2 of
131.13 + * the License, or (at your option) any later version.
131.14 + *
131.15 + * This program is distributed in the hope that it will be useful,
131.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
131.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
131.18 + * GNU General Public License for more details.
131.19 + *
131.20 + * You should have received a copy of the GNU General Public License
131.21 + * along with this program; if not, write to the Free Software
131.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
131.23 + * Boston, MA 02110-1301, USA
131.24 + */
131.25 +
131.26 +#include <l4/devices/gpio-jz4730.h>
131.27 +#include <l4/devices/dataspace.h>
131.28 +#include <l4/devices/memory.h>
131.29 +#include "keypad-server.h"
131.30 +
131.31 +#include <l4/sys/thread.h>
131.32 +#include <pthread.h>
131.33 +#include <pthread-l4.h>
131.34 +
131.35 +#include <l4/cxx/ipc_server>
131.36 +#include <l4/re/dataspace>
131.37 +#include <l4/re/env>
131.38 +#include <l4/re/rm>
131.39 +#include <l4/re/util/cap_alloc>
131.40 +#include <l4/re/util/object_registry>
131.41 +
131.42 +#include <l4/sys/cache.h>
131.43 +#include <l4/util/util.h>
131.44 +
131.45 +#include <stdint.h>
131.46 +
131.47 +enum Jz4730_keypad_gpio
131.48 +{
131.49 + Jz4730_keypad_gpio_inputs_count = 8,
131.50 + Jz4730_keypad_gpio_outputs_count = 17,
131.51 +};
131.52 +
131.53 +/* Port A input pins. */
131.54 +
131.55 +const uint8_t Jz4730_keypad_inputs[Jz4730_keypad_gpio_inputs_count] = {
131.56 + 0, 1, 2, 3, 4, 5, 6, 7
131.57 +};
131.58 +
131.59 +const Pin_slice Jz4730_keypad_inputs_mask = {0x000000ff, 0};
131.60 +
131.61 +/* Port D output pins. */
131.62 +
131.63 +const uint8_t Jz4730_keypad_outputs[Jz4730_keypad_gpio_outputs_count] = {
131.64 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29
131.65 +};
131.66 +
131.67 +const Pin_slice Jz4730_keypad_outputs_mask = {0x2000ffff, 0};
131.68 +
131.69 +/* Peripheral memory regions. */
131.70 +
131.71 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
131.72 +
131.73 +/* GPIO abstractions. */
131.74 +
131.75 +static void *gpio_port_a, *gpio_port_d;
131.76 +
131.77 +/* Keypad status: an array of keypad column values. */
131.78 +
131.79 +uint32_t *keypad = 0;
131.80 +
131.81 +/* Imported keypad memory referenced by the array. */
131.82 +
131.83 +void *keymem = 0;
131.84 +
131.85 +/* Thread details. */
131.86 +
131.87 +static pthread_t _pthread;
131.88 +
131.89 +
131.90 +
131.91 +/* Initialise the pins for scanning the keypad. */
131.92 +
131.93 +static void init_keyscan(void)
131.94 +{
131.95 + jz4730_gpio_multi_setup(gpio_port_a, &Jz4730_keypad_inputs_mask, Hw::Gpio_chip::Input, 0);
131.96 + jz4730_gpio_multi_config_pull(gpio_port_a, &Jz4730_keypad_inputs_mask, Hw::Gpio_chip::Pull_up);
131.97 + jz4730_gpio_multi_setup(gpio_port_d, &Jz4730_keypad_outputs_mask, Hw::Gpio_chip::Input, 0);
131.98 +}
131.99 +
131.100 +/*
131.101 +Scan the keypad by enabling each output column and inspecting each input row.
131.102 +Store each column bitmap in the keypad array.
131.103 +*/
131.104 +
131.105 +static void scan_keypad(void)
131.106 +{
131.107 + uint8_t column, row, value;
131.108 +
131.109 + for (column = 0; column < Jz4730_keypad_gpio_outputs_count; column++)
131.110 + {
131.111 + jz4730_gpio_setup(gpio_port_d, Jz4730_keypad_outputs[column], Hw::Gpio_chip::Output, 0);
131.112 + l4_sleep(1);
131.113 +
131.114 + value = 0;
131.115 +
131.116 + for (row = 0; row < Jz4730_keypad_gpio_inputs_count; row++)
131.117 + value = (value << 1) | (jz4730_gpio_get(gpio_port_a, Jz4730_keypad_inputs[row]) ? 0 : 1);
131.118 +
131.119 + keypad[column] = value;
131.120 +
131.121 + jz4730_gpio_setup(gpio_port_d, Jz4730_keypad_outputs[column], Hw::Gpio_chip::Input, 0);
131.122 + }
131.123 +
131.124 + l4_cache_clean_data((unsigned long) keypad,
131.125 + (unsigned long) keypad + Jz4730_keypad_gpio_outputs_count);
131.126 +}
131.127 +
131.128 +/* Set up access to memory. */
131.129 +
131.130 +static int setup_memory(void)
131.131 +{
131.132 + if (get_memory("jz4730-gpio", &gpio_virt_base, &gpio_virt_base_end) < 0)
131.133 + return 1;
131.134 +
131.135 + gpio_port_a = jz4730_gpio_init(gpio_virt_base, gpio_virt_base + 0x30, 32);
131.136 + gpio_port_d = jz4730_gpio_init(gpio_virt_base + 0x90, gpio_virt_base + 0xc0, 32);
131.137 +
131.138 + return 0;
131.139 +}
131.140 +
131.141 +
131.142 +
131.143 +/* Worker thread for scanning the keypad. */
131.144 +
131.145 +static void *scan_thread(void *data)
131.146 +{
131.147 + (void) data;
131.148 +
131.149 + while (1)
131.150 + {
131.151 + scan_keypad();
131.152 + l4_sleep(20); /* 20ms -> 50Hz */
131.153 + }
131.154 +
131.155 + return 0;
131.156 +}
131.157 +
131.158 +/* Thread initialisation. */
131.159 +
131.160 +static int init_thread(void)
131.161 +{
131.162 + pthread_attr_t thread_attr;
131.163 + struct sched_param sp;
131.164 +
131.165 + if (pthread_attr_init(&thread_attr))
131.166 + return 1;
131.167 +
131.168 + sp.sched_priority = 0x20;
131.169 + pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
131.170 + pthread_attr_setschedparam(&thread_attr, &sp);
131.171 + pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
131.172 +
131.173 + return pthread_create(&_pthread, &thread_attr, scan_thread, 0);
131.174 +}
131.175 +
131.176 +
131.177 +
131.178 +static L4Re::Util::Registry_server<> server;
131.179 +
131.180 +
131.181 +
131.182 +/* Main program. */
131.183 +
131.184 +int main(void)
131.185 +{
131.186 + /* Memory allocation capability for the keypad data. */
131.187 +
131.188 + L4::Cap<L4Re::Dataspace> mem;
131.189 + l4_size_t mem_size = Jz4730_keypad_gpio_outputs_count * sizeof(uint32_t);
131.190 +
131.191 + if (setup_memory()) return 1;
131.192 +
131.193 + mem = allocate_data(mem_size, &keymem);
131.194 +
131.195 + if (!mem.is_valid()) return 1;
131.196 +
131.197 + keypad = (uint32_t *) keymem;
131.198 +
131.199 + /* Set up keypad access and start scanning. */
131.200 +
131.201 + init_keyscan();
131.202 +
131.203 + /* Set up a thread to scan the keypad concurrently with the server loop. */
131.204 +
131.205 + init_thread();
131.206 +
131.207 + /* Initialise and register a server object. */
131.208 +
131.209 + Keypad_server server_obj(mem);
131.210 + server.registry()->register_obj(&server_obj, "keypad");
131.211 +
131.212 + /* Enter the IPC server loop. */
131.213 +
131.214 + server.loop();
131.215 + return 0;
131.216 +}
132.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
132.2 +++ b/pkg/devices/keypad/src/qi_lb60/Makefile Sun May 13 01:34:16 2018 +0200
132.3 @@ -0,0 +1,13 @@
132.4 +PKGDIR ?= ../../..
132.5 +L4DIR ?= $(PKGDIR)/../..
132.6 +
132.7 +TARGET = dev_keypad_qi_lb60
132.8 +PC_FILENAME := devices-keypad-qi_lb60
132.9 +
132.10 +SRC_CC := keypad-qi_lb60.cc
132.11 +
132.12 +PRIVATE_INCDIR += $(PKGDIR)/keypad/include
132.13 +
132.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-gpio libdevice-util libdevice-keypad-server
132.15 +
132.16 +include $(L4DIR)/mk/prog.mk
133.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
133.2 +++ b/pkg/devices/keypad/src/qi_lb60/keypad-qi_lb60.cc Sun May 13 01:34:16 2018 +0200
133.3 @@ -0,0 +1,210 @@
133.4 +/*
133.5 + * Export the keypad GPIOs on the Ben NanoNote as a data space accessible via
133.6 + * the "keypad" capability.
133.7 + *
133.8 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
133.9 + *
133.10 + * This program is free software; you can redistribute it and/or
133.11 + * modify it under the terms of the GNU General Public License as
133.12 + * published by the Free Software Foundation; either version 2 of
133.13 + * the License, or (at your option) any later version.
133.14 + *
133.15 + * This program is distributed in the hope that it will be useful,
133.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
133.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
133.18 + * GNU General Public License for more details.
133.19 + *
133.20 + * You should have received a copy of the GNU General Public License
133.21 + * along with this program; if not, write to the Free Software
133.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
133.23 + * Boston, MA 02110-1301, USA
133.24 + */
133.25 +
133.26 +#include <l4/devices/gpio-jz4740.h>
133.27 +#include <l4/devices/dataspace.h>
133.28 +#include <l4/devices/memory.h>
133.29 +#include "keypad-server.h"
133.30 +
133.31 +#include <l4/sys/thread.h>
133.32 +#include <pthread.h>
133.33 +#include <pthread-l4.h>
133.34 +
133.35 +#include <l4/re/dataspace>
133.36 +#include <l4/re/env>
133.37 +#include <l4/re/util/object_registry>
133.38 +
133.39 +#include <l4/sys/cache.h>
133.40 +#include <l4/util/util.h>
133.41 +
133.42 +#include <stdint.h>
133.43 +
133.44 +enum Jz4740_keypad_gpio
133.45 +{
133.46 + Jz4740_keypad_gpio_inputs_count = 8,
133.47 + Jz4740_keypad_gpio_outputs_count = 8,
133.48 +};
133.49 +
133.50 +/* Port D input pins. */
133.51 +
133.52 +const uint8_t Jz4740_keypad_inputs[Jz4740_keypad_gpio_inputs_count] = {
133.53 + 18, 19, 20, 21, 22, 23, 24, 26
133.54 +};
133.55 +
133.56 +const Pin_slice Jz4740_keypad_inputs_mask = {0x05fc0000, 0};
133.57 +
133.58 +/* Port C output pins. */
133.59 +
133.60 +const uint8_t Jz4740_keypad_outputs[Jz4740_keypad_gpio_outputs_count] = {
133.61 + 10, 11, 12, 13, 14, 15, 16, 17
133.62 +};
133.63 +
133.64 +const Pin_slice Jz4740_keypad_outputs_mask = {0x0003fc00, 0};
133.65 +
133.66 +/* Peripheral memory regions. */
133.67 +
133.68 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
133.69 +
133.70 +/* GPIO abstractions. */
133.71 +
133.72 +static void *gpio_port_c, *gpio_port_d;
133.73 +
133.74 +/* Keypad status: an array of keypad column values. */
133.75 +
133.76 +uint32_t *keypad = 0;
133.77 +
133.78 +/* Imported keypad memory referenced by the array. */
133.79 +
133.80 +void *keymem = 0;
133.81 +
133.82 +/* Thread details. */
133.83 +
133.84 +static pthread_t _pthread;
133.85 +
133.86 +
133.87 +
133.88 +/* Initialise the pins for scanning the keypad. */
133.89 +
133.90 +static void init_keyscan(void)
133.91 +{
133.92 + jz4740_gpio_multi_setup(gpio_port_d, &Jz4740_keypad_inputs_mask, Hw::Gpio_chip::Input, 0);
133.93 + jz4740_gpio_multi_config_pull(gpio_port_d, &Jz4740_keypad_inputs_mask, Hw::Gpio_chip::Pull_up);
133.94 + jz4740_gpio_multi_setup(gpio_port_c, &Jz4740_keypad_outputs_mask, Hw::Gpio_chip::Input, 0);
133.95 +}
133.96 +
133.97 +/*
133.98 +Scan the keypad by enabling each output column and inspecting each input row.
133.99 +Store each column bitmap in the keypad array.
133.100 +*/
133.101 +
133.102 +static void scan_keypad(void)
133.103 +{
133.104 + uint8_t column, row, value;
133.105 +
133.106 + for (column = 0; column < Jz4740_keypad_gpio_outputs_count; column++)
133.107 + {
133.108 + jz4740_gpio_setup(gpio_port_c, Jz4740_keypad_outputs[column], Hw::Gpio_chip::Output, 0);
133.109 + l4_sleep(1);
133.110 +
133.111 + value = 0;
133.112 +
133.113 + for (row = 0; row < Jz4740_keypad_gpio_inputs_count; row++)
133.114 + value = (value << 1) | (jz4740_gpio_get(gpio_port_d, Jz4740_keypad_inputs[row]) ? 0 : 1);
133.115 +
133.116 + keypad[column] = value;
133.117 +
133.118 + jz4740_gpio_setup(gpio_port_c, Jz4740_keypad_outputs[column], Hw::Gpio_chip::Input, 0);
133.119 + }
133.120 +
133.121 + l4_cache_clean_data((unsigned long) keypad,
133.122 + (unsigned long) keypad + Jz4740_keypad_gpio_outputs_count);
133.123 +}
133.124 +
133.125 +/* Set up access to memory. */
133.126 +
133.127 +static int setup_memory(void)
133.128 +{
133.129 + if (get_memory("jz4740-gpio", &gpio_virt_base, &gpio_virt_base_end) < 0)
133.130 + return 1;
133.131 +
133.132 + gpio_port_c = jz4740_gpio_init(gpio_virt_base + 0x200, gpio_virt_base + 0x300, 32);
133.133 + gpio_port_d = jz4740_gpio_init(gpio_virt_base + 0x300, gpio_virt_base + 0x400, 32);
133.134 +
133.135 + return 0;
133.136 +}
133.137 +
133.138 +
133.139 +
133.140 +/* Worker thread for scanning the keypad. */
133.141 +
133.142 +static void *scan_thread(void *data)
133.143 +{
133.144 + (void) data;
133.145 +
133.146 + while (1)
133.147 + {
133.148 + scan_keypad();
133.149 + l4_sleep(20); /* 20ms -> 50Hz */
133.150 + }
133.151 +
133.152 + return 0;
133.153 +}
133.154 +
133.155 +/* Thread initialisation. */
133.156 +
133.157 +static int init_thread(void)
133.158 +{
133.159 + pthread_attr_t thread_attr;
133.160 + struct sched_param sp;
133.161 +
133.162 + if (pthread_attr_init(&thread_attr))
133.163 + return 1;
133.164 +
133.165 + sp.sched_priority = 0x20;
133.166 + pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
133.167 + pthread_attr_setschedparam(&thread_attr, &sp);
133.168 + pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
133.169 +
133.170 + return pthread_create(&_pthread, &thread_attr, scan_thread, 0);
133.171 +}
133.172 +
133.173 +
133.174 +
133.175 +static L4Re::Util::Registry_server<> server;
133.176 +
133.177 +
133.178 +
133.179 +/* Main program. */
133.180 +
133.181 +int main(void)
133.182 +{
133.183 + /* Memory allocation capability for the keypad data. */
133.184 +
133.185 + L4::Cap<L4Re::Dataspace> mem;
133.186 + l4_size_t mem_size = Jz4740_keypad_gpio_outputs_count * sizeof(uint32_t);
133.187 +
133.188 + if (setup_memory()) return 1;
133.189 +
133.190 + mem = allocate_data(mem_size, &keymem);
133.191 +
133.192 + if (!mem.is_valid()) return 1;
133.193 +
133.194 + keypad = (uint32_t *) keymem;
133.195 +
133.196 + /* Set up keypad access and start scanning. */
133.197 +
133.198 + init_keyscan();
133.199 +
133.200 + /* Set up a thread to scan the keypad concurrently with the server loop. */
133.201 +
133.202 + init_thread();
133.203 +
133.204 + /* Initialise and register a server object. */
133.205 +
133.206 + Keypad_server server_obj(mem);
133.207 + server.registry()->register_obj(&server_obj, "keypad");
133.208 +
133.209 + /* Enter the IPC server loop. */
133.210 +
133.211 + server.loop();
133.212 + return 0;
133.213 +}
134.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
134.2 +++ b/pkg/devices/keypad/src/server/Makefile Sun May 13 01:34:16 2018 +0200
134.3 @@ -0,0 +1,13 @@
134.4 +PKGDIR ?= ../../..
134.5 +L4DIR ?= $(PKGDIR)/../..
134.6 +
134.7 +TARGET = libdevice_keypad_server.o.a
134.8 +PC_FILENAME := libdevice-keypad-server
134.9 +
134.10 +SRC_CC := keypad-server.cc
134.11 +
134.12 +PRIVATE_INCDIR += $(PKGDIR)/keypad/include
134.13 +
134.14 +REQUIRES_LIBS := l4re_c l4re_c-util
134.15 +
134.16 +include $(L4DIR)/mk/lib.mk
135.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
135.2 +++ b/pkg/devices/keypad/src/server/keypad-server.cc Sun May 13 01:34:16 2018 +0200
135.3 @@ -0,0 +1,52 @@
135.4 +/*
135.5 + * Common keypad server functionality.
135.6 + *
135.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
135.8 + *
135.9 + * This program is free software; you can redistribute it and/or
135.10 + * modify it under the terms of the GNU General Public License as
135.11 + * published by the Free Software Foundation; either version 2 of
135.12 + * the License, or (at your option) any later version.
135.13 + *
135.14 + * This program is distributed in the hope that it will be useful,
135.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
135.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
135.17 + * GNU General Public License for more details.
135.18 + *
135.19 + * You should have received a copy of the GNU General Public License
135.20 + * along with this program; if not, write to the Free Software
135.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
135.22 + * Boston, MA 02110-1301, USA
135.23 + */
135.24 +
135.25 +#include "keypad-client.h"
135.26 +#include "keypad-server.h"
135.27 +
135.28 +#include <l4/cxx/ipc_server>
135.29 +#include <l4/re/env>
135.30 +#include <l4/sys/typeinfo_svr>
135.31 +#include <l4/util/util.h>
135.32 +
135.33 +/* Handle invocations. */
135.34 +
135.35 +int
135.36 +Keypad_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
135.37 +{
135.38 + l4_msgtag_t tag;
135.39 +
135.40 + (void) obj;
135.41 + ios >> tag;
135.42 +
135.43 + switch (tag.label())
135.44 + {
135.45 + case L4::Meta::Protocol:
135.46 + return L4::Util::handle_meta_request<Keypad_device_interface>(ios);
135.47 +
135.48 + case Keypad_op_get_keypad_data:
135.49 + ios << _mem;
135.50 + return L4_EOK;
135.51 +
135.52 + default:
135.53 + return -L4_EBADPROTO;
135.54 + }
135.55 +}
136.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
136.2 +++ b/pkg/devices/lcd/Makefile Sun May 13 01:34:16 2018 +0200
136.3 @@ -0,0 +1,8 @@
136.4 +PKGDIR ?= ..
136.5 +L4DIR ?= $(PKGDIR)/../..
136.6 +
136.7 +TARGET := include src
136.8 +
136.9 +include $(L4DIR)/mk/subdir.mk
136.10 +
136.11 +src: include
137.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
137.2 +++ b/pkg/devices/lcd/include/Makefile Sun May 13 01:34:16 2018 +0200
137.3 @@ -0,0 +1,4 @@
137.4 +PKGDIR = ../..
137.5 +L4DIR ?= $(PKGDIR)/../..
137.6 +
137.7 +include $(L4DIR)/mk/include.mk
138.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
138.2 +++ b/pkg/devices/lcd/include/lcd-device.h Sun May 13 01:34:16 2018 +0200
138.3 @@ -0,0 +1,112 @@
138.4 +/*
138.5 + * LCD device support.
138.6 + *
138.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
138.8 + *
138.9 + * This program is free software; you can redistribute it and/or
138.10 + * modify it under the terms of the GNU General Public License as
138.11 + * published by the Free Software Foundation; either version 2 of
138.12 + * the License, or (at your option) any later version.
138.13 + *
138.14 + * This program is distributed in the hope that it will be useful,
138.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
138.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138.17 + * GNU General Public License for more details.
138.18 + *
138.19 + * You should have received a copy of the GNU General Public License
138.20 + * along with this program; if not, write to the Free Software
138.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
138.22 + * Boston, MA 02110-1301, USA
138.23 + */
138.24 +
138.25 +#pragma once
138.26 +
138.27 +#include <l4/devices/display-client.h>
138.28 +#include <l4/devices/lcd.h>
138.29 +
138.30 +#include <l4/re/c/video/view.h>
138.31 +#include <l4/sys/types.h>
138.32 +
138.33 +
138.34 +
138.35 +#ifdef __cplusplus
138.36 +
138.37 +#include <l4/re/dataspace>
138.38 +#include <l4/sys/capability>
138.39 +
138.40 +class Lcd_device
138.41 +{
138.42 +protected:
138.43 + /* LCD peripheral abstraction. */
138.44 +
138.45 + Lcd_chip *_chip;
138.46 +
138.47 + /* Display server abstraction. */
138.48 +
138.49 + L4::Cap<Display_device_interface> _display;
138.50 +
138.51 + /* Framebuffer virtual and physical addresses. */
138.52 +
138.53 + l4_addr_t fb_vaddr, fb_paddr;
138.54 +
138.55 + /* Memory capability for the framebuffer. */
138.56 +
138.57 + L4::Cap<L4Re::Dataspace> _fbmem;
138.58 +
138.59 + /* Display operations. */
138.60 +
138.61 + virtual void disable_display();
138.62 + virtual void enable_display();
138.63 +
138.64 +public:
138.65 + /* Initialise a device with a controller and display object reference. */
138.66 +
138.67 + Lcd_device(Lcd_chip *chip, L4::Cap<Display_device_interface> display)
138.68 + : _chip(chip), _display(display)
138.69 + {
138.70 + /* Subclasses must set up any memory. */
138.71 + }
138.72 +
138.73 + /* Framebuffer operations. */
138.74 +
138.75 + virtual l4_addr_t get_framebuffer()
138.76 + {
138.77 + return fb_vaddr;
138.78 + }
138.79 +
138.80 + virtual L4::Cap<L4Re::Dataspace> get_framebuffer_cap()
138.81 + {
138.82 + return _fbmem;
138.83 + }
138.84 +
138.85 + /* Querying operations. */
138.86 +
138.87 + virtual l4_size_t get_framebuffer_size() = 0;
138.88 + virtual void get_view_info(l4re_video_view_info_t *view_info) = 0;
138.89 +
138.90 + /* Device operations. */
138.91 +
138.92 + virtual void disable() = 0;
138.93 + virtual void enable() = 0;
138.94 +
138.95 + /* Device access. */
138.96 +
138.97 + static Lcd_device *get_device();
138.98 +};
138.99 +
138.100 +#endif
138.101 +
138.102 +
138.103 +
138.104 +/* C language interface. */
138.105 +
138.106 +EXTERN_C_BEGIN
138.107 +
138.108 +void *lcd_get_device(void);
138.109 +l4_addr_t lcd_get_framebuffer(void *lcd);
138.110 +l4_size_t lcd_get_framebuffer_size(void *lcd);
138.111 +void lcd_get_view_info(void *lcd, l4re_video_view_info_t *view_info);
138.112 +void lcd_disable(void *lcd);
138.113 +void lcd_enable(void *lcd);
138.114 +
138.115 +EXTERN_C_END
139.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
139.2 +++ b/pkg/devices/lcd/include/lcd-jz4740-device.h Sun May 13 01:34:16 2018 +0200
139.3 @@ -0,0 +1,73 @@
139.4 +/*
139.5 + * LCD device support for the JZ4740 and related SoCs.
139.6 + *
139.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
139.8 + *
139.9 + * This program is free software; you can redistribute it and/or
139.10 + * modify it under the terms of the GNU General Public License as
139.11 + * published by the Free Software Foundation; either version 2 of
139.12 + * the License, or (at your option) any later version.
139.13 + *
139.14 + * This program is distributed in the hope that it will be useful,
139.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
139.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
139.17 + * GNU General Public License for more details.
139.18 + *
139.19 + * You should have received a copy of the GNU General Public License
139.20 + * along with this program; if not, write to the Free Software
139.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
139.22 + * Boston, MA 02110-1301, USA
139.23 + */
139.24 +
139.25 +#pragma once
139.26 +
139.27 +#include <l4/devices/lcd.h>
139.28 +#include "lcd-device.h"
139.29 +
139.30 +#include <l4/re/c/video/view.h>
139.31 +#include <l4/sys/types.h>
139.32 +
139.33 +/* C++ language interface. */
139.34 +
139.35 +#ifdef __cplusplus
139.36 +
139.37 +/* Support for specific JZ4740-based devices. */
139.38 +
139.39 +class Lcd_jz4740_device : public Lcd_device
139.40 +{
139.41 + /* DMA descriptor virtual and physical addresses. */
139.42 +
139.43 + l4_addr_t desc_vaddr, desc_paddr;
139.44 +
139.45 +protected:
139.46 + /* Device-specific memory allocation. */
139.47 +
139.48 + int _setup_memory();
139.49 +
139.50 +public:
139.51 + /* Inherit constructor. */
139.52 +
139.53 + Lcd_jz4740_device(Lcd_chip *chip, L4::Cap<Display_device_interface> display)
139.54 + : Lcd_device(chip, display)
139.55 + {
139.56 + _setup_memory();
139.57 + }
139.58 +
139.59 + /* Device operations. */
139.60 +
139.61 + void disable();
139.62 + void enable();
139.63 +
139.64 + l4_size_t get_framebuffer_size()
139.65 + {
139.66 + return static_cast<Lcd_jz4740_chip *>(_chip)->get_screen_size();
139.67 + }
139.68 +
139.69 + void get_view_info(l4re_video_view_info_t *view_info);
139.70 +
139.71 + /* Common device instance. */
139.72 +
139.73 + static Lcd_jz4740_device *device;
139.74 +};
139.75 +
139.76 +#endif
140.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
140.2 +++ b/pkg/devices/lcd/include/lcd-letux400.h Sun May 13 01:34:16 2018 +0200
140.3 @@ -0,0 +1,43 @@
140.4 +/*
140.5 + * LCD device support for the Letux 400 notebook computer.
140.6 + *
140.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
140.8 + *
140.9 + * This program is free software; you can redistribute it and/or
140.10 + * modify it under the terms of the GNU General Public License as
140.11 + * published by the Free Software Foundation; either version 2 of
140.12 + * the License, or (at your option) any later version.
140.13 + *
140.14 + * This program is distributed in the hope that it will be useful,
140.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
140.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
140.17 + * GNU General Public License for more details.
140.18 + *
140.19 + * You should have received a copy of the GNU General Public License
140.20 + * along with this program; if not, write to the Free Software
140.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
140.22 + * Boston, MA 02110-1301, USA
140.23 + */
140.24 +
140.25 +#pragma once
140.26 +
140.27 +#include "lcd-jz4740-device.h"
140.28 +
140.29 +#ifdef __cplusplus
140.30 +
140.31 +class Lcd_letux400 : public Lcd_jz4740_device
140.32 +{
140.33 +public:
140.34 + /* Inherit constructor. */
140.35 +
140.36 + Lcd_letux400(Lcd_chip *chip, L4::Cap<Display_device_interface> display)
140.37 + : Lcd_jz4740_device(chip, display)
140.38 + {
140.39 + }
140.40 +
140.41 + /* Common device instance. */
140.42 +
140.43 + static Lcd_letux400 *device;
140.44 +};
140.45 +
140.46 +#endif
141.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
141.2 +++ b/pkg/devices/lcd/include/lcd-qi_lb60.h Sun May 13 01:34:16 2018 +0200
141.3 @@ -0,0 +1,43 @@
141.4 +/*
141.5 + * LCD device support for the Ben NanoNote.
141.6 + *
141.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
141.8 + *
141.9 + * This program is free software; you can redistribute it and/or
141.10 + * modify it under the terms of the GNU General Public License as
141.11 + * published by the Free Software Foundation; either version 2 of
141.12 + * the License, or (at your option) any later version.
141.13 + *
141.14 + * This program is distributed in the hope that it will be useful,
141.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
141.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141.17 + * GNU General Public License for more details.
141.18 + *
141.19 + * You should have received a copy of the GNU General Public License
141.20 + * along with this program; if not, write to the Free Software
141.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
141.22 + * Boston, MA 02110-1301, USA
141.23 + */
141.24 +
141.25 +#pragma once
141.26 +
141.27 +#include "lcd-jz4740-device.h"
141.28 +
141.29 +#ifdef __cplusplus
141.30 +
141.31 +class Lcd_qi_lb60 : public Lcd_jz4740_device
141.32 +{
141.33 +public:
141.34 + /* Inherit constructor. */
141.35 +
141.36 + Lcd_qi_lb60(Lcd_chip *chip, L4::Cap<Display_device_interface> display)
141.37 + : Lcd_jz4740_device(chip, display)
141.38 + {
141.39 + }
141.40 +
141.41 + /* Common device instance. */
141.42 +
141.43 + static Lcd_qi_lb60 *device;
141.44 +};
141.45 +
141.46 +#endif
142.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
142.2 +++ b/pkg/devices/lcd/src/Makefile Sun May 13 01:34:16 2018 +0200
142.3 @@ -0,0 +1,8 @@
142.4 +PKGDIR ?= ../..
142.5 +L4DIR ?= $(PKGDIR)/../..
142.6 +
142.7 +TARGET := common jz4740
142.8 +
142.9 +include $(L4DIR)/mk/subdir.mk
142.10 +
142.11 +jz4740: common
143.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
143.2 +++ b/pkg/devices/lcd/src/common/Makefile Sun May 13 01:34:16 2018 +0200
143.3 @@ -0,0 +1,13 @@
143.4 +PKGDIR ?= ../../..
143.5 +L4DIR ?= $(PKGDIR)/../..
143.6 +
143.7 +TARGET = liblcd_device.o.a
143.8 +PC_FILENAME := libdevice-lcd
143.9 +
143.10 +SRC_CC := lcd-device.cc
143.11 +
143.12 +PRIVATE_INCDIR += $(PKGDIR)/lcd/include
143.13 +
143.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-display-client libdrivers-lcd-headers
143.15 +
143.16 +include $(L4DIR)/mk/lib.mk
144.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
144.2 +++ b/pkg/devices/lcd/src/common/lcd-device.cc Sun May 13 01:34:16 2018 +0200
144.3 @@ -0,0 +1,64 @@
144.4 +/*
144.5 + * Common LCD device functionality.
144.6 + *
144.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
144.8 + *
144.9 + * This program is free software; you can redistribute it and/or
144.10 + * modify it under the terms of the GNU General Public License as
144.11 + * published by the Free Software Foundation; either version 2 of
144.12 + * the License, or (at your option) any later version.
144.13 + *
144.14 + * This program is distributed in the hope that it will be useful,
144.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
144.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144.17 + * GNU General Public License for more details.
144.18 + *
144.19 + * You should have received a copy of the GNU General Public License
144.20 + * along with this program; if not, write to the Free Software
144.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
144.22 + * Boston, MA 02110-1301, USA
144.23 + */
144.24 +
144.25 +#include "lcd-device.h"
144.26 +
144.27 +void Lcd_device::disable_display()
144.28 +{
144.29 + _display->disable();
144.30 +}
144.31 +
144.32 +void Lcd_device::enable_display()
144.33 +{
144.34 + _display->enable();
144.35 +}
144.36 +
144.37 +// C language interface.
144.38 +
144.39 +void *lcd_get_device()
144.40 +{
144.41 + return (void *) Lcd_device::get_device();
144.42 +}
144.43 +
144.44 +l4_addr_t lcd_get_framebuffer(void *lcd)
144.45 +{
144.46 + return static_cast<Lcd_device *>(lcd)->get_framebuffer();
144.47 +}
144.48 +
144.49 +l4_size_t lcd_get_framebuffer_size(void *lcd)
144.50 +{
144.51 + return static_cast<Lcd_device *>(lcd)->get_framebuffer_size();
144.52 +}
144.53 +
144.54 +void lcd_get_view_info(void *lcd, l4re_video_view_info_t *view_info)
144.55 +{
144.56 + return static_cast<Lcd_device *>(lcd)->get_view_info(view_info);
144.57 +}
144.58 +
144.59 +void lcd_disable(void *lcd)
144.60 +{
144.61 + static_cast<Lcd_device *>(lcd)->disable();
144.62 +}
144.63 +
144.64 +void lcd_enable(void *lcd)
144.65 +{
144.66 + static_cast<Lcd_device *>(lcd)->enable();
144.67 +}
145.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
145.2 +++ b/pkg/devices/lcd/src/jz4740/Makefile Sun May 13 01:34:16 2018 +0200
145.3 @@ -0,0 +1,13 @@
145.4 +PKGDIR ?= ../../..
145.5 +L4DIR ?= $(PKGDIR)/../..
145.6 +
145.7 +TARGET = liblcd_dev_jz4740.o.a
145.8 +PC_FILENAME := libdevice-lcd-jz4740
145.9 +
145.10 +SRC_CC := lcd-jz4740-device.cc
145.11 +
145.12 +PRIVATE_INCDIR += $(PKGDIR)/lcd/include
145.13 +
145.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-lcd libdrivers-lcd-jz4740 libdevice-cpm-client libdevice-panel-client libdevice-util
145.15 +
145.16 +include $(L4DIR)/mk/lib.mk
146.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
146.2 +++ b/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc Sun May 13 01:34:16 2018 +0200
146.3 @@ -0,0 +1,280 @@
146.4 +/*
146.5 + * Common LCD device support for the JZ4740 and related SoCs.
146.6 + *
146.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
146.8 + *
146.9 + * This program is free software; you can redistribute it and/or
146.10 + * modify it under the terms of the GNU General Public License as
146.11 + * published by the Free Software Foundation; either version 2 of
146.12 + * the License, or (at your option) any later version.
146.13 + *
146.14 + * This program is distributed in the hope that it will be useful,
146.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
146.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
146.17 + * GNU General Public License for more details.
146.18 + *
146.19 + * You should have received a copy of the GNU General Public License
146.20 + * along with this program; if not, write to the Free Software
146.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
146.22 + * Boston, MA 02110-1301, USA
146.23 + */
146.24 +
146.25 +#include <l4/devices/cpm-client.h>
146.26 +#include <l4/devices/display-client.h>
146.27 +#include <l4/devices/panel-client.h>
146.28 +#include <l4/devices/lcd-jz4740.h>
146.29 +#include <l4/devices/memory.h>
146.30 +#include "lcd-jz4740-device.h"
146.31 +
146.32 +#include <l4/re/dataspace>
146.33 +#include <l4/re/env>
146.34 +#include <l4/re/mem_alloc>
146.35 +#include <l4/re/rm>
146.36 +#include <l4/re/util/cap_alloc>
146.37 +#include <l4/sys/types.h>
146.38 +
146.39 +#include <stdint.h>
146.40 +
146.41 +// Virtual addresses for the LCD register block.
146.42 +
146.43 +static l4_addr_t lcd_virt_base = 0, lcd_virt_base_end = 0;
146.44 +
146.45 +// LCD, CPM, display and panel device abstractions.
146.46 +
146.47 +static Lcd_jz4740_chip *lcd_chip = 0;
146.48 +
146.49 +static L4::Cap<Cpm_device_interface> cpm_device;
146.50 +static L4::Cap<Display_device_interface> display_device;
146.51 +static L4::Cap<Panel_device_interface> panel_device;
146.52 +
146.53 +// Panel definition.
146.54 +
146.55 +static struct Jz4740_lcd_panel panel;
146.56 +
146.57 +
146.58 +
146.59 +// CPM operations.
146.60 +
146.61 +static void set_timing()
146.62 +{
146.63 + uint32_t pclk = lcd_chip->get_pixel_clock();
146.64 +
146.65 + cpm_device->stop_lcd();
146.66 +
146.67 + // Original comment: LCDClock > 2.5*Pixclock
146.68 + // However, the documentation indicates that a TFT panel needs a device clock
146.69 + // 1.5 times that of the pixel clock, and a STN panel needs a device clock 3
146.70 + // times that of the pixel clock.
146.71 +
146.72 + cpm_device->set_lcd_frequencies(pclk, 3);
146.73 + cpm_device->update_output_frequency();
146.74 + cpm_device->start_lcd();
146.75 +
146.76 + l4_sleep(1); // 1ms == 1000us
146.77 +}
146.78 +
146.79 +
146.80 +
146.81 +// Disable the display.
146.82 +
146.83 +void
146.84 +Lcd_jz4740_device::disable()
146.85 +{
146.86 + Lcd_jz4740_chip *chip = static_cast<Lcd_jz4740_chip *>(_chip);
146.87 +
146.88 + disable_display();
146.89 + chip->disable();
146.90 +}
146.91 +
146.92 +// Configure the peripheral and enable the display.
146.93 +
146.94 +void
146.95 +Lcd_jz4740_device::enable()
146.96 +{
146.97 + Lcd_jz4740_chip *chip = static_cast<Lcd_jz4740_chip *>(_chip);
146.98 +
146.99 + chip->disable();
146.100 + chip->config((struct Jz4740_lcd_descriptor *) desc_vaddr,
146.101 + (struct Jz4740_lcd_descriptor *) desc_paddr,
146.102 + fb_paddr);
146.103 +
146.104 + // Initialise the clocks for the LCD controller.
146.105 +
146.106 + set_timing();
146.107 + enable_display();
146.108 +
146.109 + chip->enable();
146.110 +}
146.111 +
146.112 +// Set up memory addresses for the peripheral, initialising the framebuffer and
146.113 +// descriptor members.
146.114 +
146.115 +int
146.116 +Lcd_jz4740_device::_setup_memory()
146.117 +{
146.118 + // Framebuffer and descriptor sizes.
146.119 +
146.120 + unsigned long fb_size, desc_size;
146.121 +
146.122 + // Size of physically contiguous regions to be allocated.
146.123 +
146.124 + l4_size_t fb_size_out, desc_size_out;
146.125 +
146.126 + // Memory allocation capability.
146.127 +
146.128 + L4::Cap<L4Re::Dataspace> descmem;
146.129 +
146.130 + // Test for existing setup.
146.131 +
146.132 + if (fb_vaddr)
146.133 + return 0;
146.134 +
146.135 + // Obtain capabilities for allocating memory.
146.136 +
146.137 + _fbmem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
146.138 + if (!_fbmem.is_valid()) return 1;
146.139 +
146.140 + descmem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
146.141 + if (!descmem.is_valid()) return 1;
146.142 +
146.143 + // Obtain the memory requirements.
146.144 +
146.145 + Lcd_jz4740_chip *chip = static_cast<Lcd_jz4740_chip *>(_chip);
146.146 +
146.147 + fb_size = chip->get_screen_size();
146.148 + desc_size = chip->get_descriptors_size();
146.149 +
146.150 + // Allocate memory for the framebuffer at 2**6 == 64 byte == 16 word alignment,
146.151 + // also for the descriptors.
146.152 +
146.153 + const l4_size_t alloc_flags = L4Re::Mem_alloc::Continuous | L4Re::Mem_alloc::Pinned;
146.154 +
146.155 + if (L4Re::Env::env()->mem_alloc()->alloc(fb_size, _fbmem, alloc_flags, 6) ||
146.156 + L4Re::Env::env()->mem_alloc()->alloc(desc_size, descmem, alloc_flags, 6))
146.157 + return 1;
146.158 +
146.159 + // Map the allocated memory, obtaining virtual addresses.
146.160 +
146.161 + const l4_size_t attach_flags = L4Re::Rm::Search_addr | L4Re::Rm::Eager_map;
146.162 +
146.163 + fb_vaddr = 0;
146.164 + desc_vaddr = 0;
146.165 +
146.166 + if (L4Re::Env::env()->rm()->attach(&fb_vaddr, fb_size, attach_flags, _fbmem, 0) ||
146.167 + L4Re::Env::env()->rm()->attach(&desc_vaddr, desc_size, attach_flags, descmem, 0))
146.168 + return 1;
146.169 +
146.170 + // Obtain physical addresses for the framebuffer and descriptors.
146.171 +
146.172 + fb_paddr = 0;
146.173 + desc_paddr = 0;
146.174 +
146.175 + fb_size_out = fb_size;
146.176 + desc_size_out = desc_size;
146.177 +
146.178 + if (_fbmem->phys(0, fb_paddr, fb_size_out) ||
146.179 + descmem->phys(0, desc_paddr, desc_size_out))
146.180 + return 1;
146.181 +
146.182 + // Test the mapped region sizes.
146.183 +
146.184 + if ((fb_size_out != fb_size) || (desc_size_out != desc_size))
146.185 + return 1;
146.186 +
146.187 + return 0;
146.188 +}
146.189 +
146.190 +// Populate a view information structure.
146.191 +
146.192 +void
146.193 +Lcd_jz4740_device::get_view_info(l4re_video_view_info_t *view_info)
146.194 +{
146.195 + // Populate the L4Re framebuffer description with details from the
146.196 + // somewhat similar panel description.
146.197 +
146.198 + Lcd_jz4740_chip *chip = static_cast<Lcd_jz4740_chip *>(_chip);
146.199 + struct Jz4740_lcd_panel *panel = chip->get_panel();
146.200 +
146.201 + view_info->width = panel->width;
146.202 + view_info->height = panel->height;
146.203 + view_info->pixel_info.bytes_per_pixel = (panel->bpp + 7) / 8;
146.204 + view_info->bytes_per_line = chip->get_line_size();
146.205 +
146.206 + switch (panel->bpp)
146.207 + {
146.208 + case 32:
146.209 + view_info->pixel_info.r.shift = 16; view_info->pixel_info.r.size = 8;
146.210 + view_info->pixel_info.g.shift = 8; view_info->pixel_info.g.size = 8;
146.211 + view_info->pixel_info.b.shift = 0; view_info->pixel_info.b.size = 8;
146.212 + break;
146.213 +
146.214 + case 8:
146.215 + view_info->pixel_info.r.shift = 5; view_info->pixel_info.r.size = 3;
146.216 + view_info->pixel_info.g.shift = 2; view_info->pixel_info.g.size = 3;
146.217 + view_info->pixel_info.b.shift = 0; view_info->pixel_info.b.size = 2;
146.218 + break;
146.219 +
146.220 + case 4:
146.221 + view_info->pixel_info.r.shift = 3; view_info->pixel_info.r.size = 1;
146.222 + view_info->pixel_info.g.shift = 1; view_info->pixel_info.g.size = 2;
146.223 + view_info->pixel_info.b.shift = 0; view_info->pixel_info.b.size = 1;
146.224 + break;
146.225 +
146.226 + case 16:
146.227 + default:
146.228 + view_info->pixel_info.r.shift = 11; view_info->pixel_info.r.size = 5;
146.229 + view_info->pixel_info.g.shift = 5; view_info->pixel_info.g.size = 6;
146.230 + view_info->pixel_info.b.shift = 0; view_info->pixel_info.b.size = 5;
146.231 + break;
146.232 + }
146.233 +
146.234 + view_info->pixel_info.a.shift = 0;
146.235 + view_info->pixel_info.a.size = 0;
146.236 +}
146.237 +
146.238 +// Access to peripheral memory.
146.239 +
146.240 +static int setup_memory()
146.241 +{
146.242 + if (get_memory("jz4740-lcd", &lcd_virt_base, &lcd_virt_base_end))
146.243 + return 1;
146.244 +
146.245 + // Obtain access to the CPM, display and panel devices.
146.246 +
146.247 + cpm_device = L4Re::Env::env()->get_cap<Cpm_device_interface>("cpm");
146.248 + if (!cpm_device.is_valid()) return 1;
146.249 +
146.250 + display_device = L4Re::Env::env()->get_cap<Display_device_interface>("display");
146.251 + if (!display_device.is_valid()) return 1;
146.252 +
146.253 + panel_device = L4Re::Env::env()->get_cap<Panel_device_interface>("panel");
146.254 + if (!panel_device.is_valid()) return 1;
146.255 +
146.256 + // Populate the panel.
146.257 +
146.258 + if (panel_device->get_panel((uint8_t *) &panel, sizeof(panel)))
146.259 + return 1;
146.260 +
146.261 + // Initialise the LCD abstraction.
146.262 +
146.263 + lcd_chip = new Lcd_jz4740_chip(lcd_virt_base, &panel);
146.264 +
146.265 + return 0;
146.266 +}
146.267 +
146.268 +// Device initialisation.
146.269 +
146.270 +Lcd_jz4740_device *Lcd_jz4740_device::device = 0;
146.271 +
146.272 +Lcd_device *Lcd_device::get_device()
146.273 +{
146.274 + if (Lcd_jz4740_device::device) return Lcd_jz4740_device::device;
146.275 +
146.276 + if (setup_memory()) return 0;
146.277 +
146.278 + // Initialise the common device.
146.279 +
146.280 + Lcd_jz4740_device::device = new Lcd_jz4740_device(lcd_chip, display_device);
146.281 +
146.282 + return Lcd_jz4740_device::device;
146.283 +}
148.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148.2 +++ b/pkg/devices/lib/common/Makefile Sun May 13 01:34:16 2018 +0200
148.3 @@ -0,0 +1,6 @@
148.4 +PKGDIR ?= ../..
148.5 +L4DIR ?= $(PKGDIR)/../..
148.6 +
148.7 +TARGET := include
148.8 +
148.9 +include $(L4DIR)/mk/subdir.mk
149.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
149.2 +++ b/pkg/devices/lib/common/include/Makefile Sun May 13 01:34:16 2018 +0200
149.3 @@ -0,0 +1,6 @@
149.4 +PKGDIR = ../../..
149.5 +L4DIR ?= $(PKGDIR)/../..
149.6 +
149.7 +PC_FILENAME := libdrivers-common
149.8 +
149.9 +include $(L4DIR)/mk/include.mk
150.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
150.2 +++ b/pkg/devices/lib/common/include/hw_mmio_register_block.h Sun May 13 01:34:16 2018 +0200
150.3 @@ -0,0 +1,47 @@
150.4 +/*
150.5 + * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
150.6 + *
150.7 + * This file is part of TUD:OS and distributed under the terms of the
150.8 + * GNU General Public License 2.
150.9 + * Please see the COPYING-GPL-2 file for details.
150.10 + */
150.11 +#pragma once
150.12 +
150.13 +#include "hw_register_block.h"
150.14 +
150.15 +namespace Hw {
150.16 +
150.17 +class Mmio_register_block_base
150.18 +{
150.19 +private:
150.20 + l4_addr_t _base;
150.21 + l4_addr_t _shift;
150.22 +
150.23 +public:
150.24 + explicit Mmio_register_block_base(l4_addr_t base = 0, l4_addr_t shift = 0)
150.25 + : _base(base), _shift(shift) {}
150.26 +
150.27 + template< typename T >
150.28 + T read(l4_addr_t reg) const
150.29 + { return *reinterpret_cast<volatile const T *>(_base + (reg << _shift)); }
150.30 +
150.31 + template< typename T >
150.32 + void write(T value, l4_addr_t reg) const
150.33 + { *reinterpret_cast<volatile T *>(_base + (reg << _shift)) = value; }
150.34 +
150.35 + void set_base(l4_addr_t base) { _base = base; }
150.36 + void set_shift(l4_addr_t shift) { _shift = shift; }
150.37 +};
150.38 +
150.39 +template< unsigned MAX_BITS = 32 >
150.40 +struct Mmio_register_block :
150.41 + Register_block_impl<Mmio_register_block<MAX_BITS>, MAX_BITS>,
150.42 + Mmio_register_block_base
150.43 +{
150.44 + explicit Mmio_register_block(l4_addr_t base = 0, l4_addr_t shift = 0)
150.45 + : Mmio_register_block_base(base, shift) {}
150.46 +};
150.47 +
150.48 +}
150.49 +
150.50 +
151.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
151.2 +++ b/pkg/devices/lib/common/include/hw_register_block.h Sun May 13 01:34:16 2018 +0200
151.3 @@ -0,0 +1,499 @@
151.4 +/*
151.5 + * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
151.6 + *
151.7 + * This file is part of TUD:OS and distributed under the terms of the
151.8 + * GNU General Public License 2.
151.9 + * Please see the COPYING-GPL-2 file for details.
151.10 + */
151.11 +#pragma once
151.12 +
151.13 +#include <l4/sys/types.h>
151.14 +#include <l4/cxx/type_traits>
151.15 +
151.16 +namespace Hw {
151.17 +
151.18 +
151.19 +/* EXAMPLE usage:
151.20 +
151.21 +\code
151.22 +
151.23 +void test()
151.24 +{
151.25 + // create a register block reference for max. 16bit accesses, using a
151.26 + // MMIO register block implementation (at address 0x1000).
151.27 + Hw::Register_block<16> regs = new Hw::Mmio_register_block<16>(0x1000);
151.28 +
151.29 + // Alternatively it is allowed to use an implementation that allows
151.30 + // wider access than actually needed.
151.31 + Hw::Register_block<16> regs = new Hw::Mmio_register_block<32>(0x1000);
151.32 +
151.33 + // read a 16bit register at offset 8byte
151.34 + unsigned short x = regs.r<16>(8);
151.35 + unsigned short x1 = regs[8]; // alternative
151.36 +
151.37 + // read an 8bit register at offset 0byte
151.38 + unsigned v = regs.r<8>(0);
151.39 +
151.40 + // do a 16bit write to register at offset 2byte (four variants)
151.41 + regs[2] = 22;
151.42 + regs.r<16>(2) = 22;
151.43 + regs[2].write(22);
151.44 + regs.r<16>().write(22);
151.45 +
151.46 + // do an 8bit write (two variants)
151.47 + regs.r<8>(0) = 9;
151.48 + regs.r<8>(0).write(9);
151.49 +
151.50 + // do 16bit read-modify-write (two variants)
151.51 + regs[4].modify(0xf, 3); // clear 4 lowest bits and set them to 3
151.52 + regs.r<16>(4).modify(0xf, 3);
151.53 +
151.54 + // do 8bit read-modify-write
151.55 + regs.r<8>(0).modify(0xf, 3);
151.56 +
151.57 + // fails to compile, because of too wide access
151.58 + // (32 bit access but regs is Hw::Register_block<16>)
151.59 + unsigned long v = regs.r<32>(4)
151.60 +}
151.61 +
151.62 +\endcode
151.63 +*/
151.64 +
151.65 +
151.66 +/**
151.67 + * \brief Abstract register block interface
151.68 + * \tparam MAX_BITS The maximum access width for the registers.
151.69 + *
151.70 + * This interfaces is based on virtual do_read_<xx> and do_write_<xx>
151.71 + * methods that have to be implemented up to the maximum access width.
151.72 + */
151.73 +template< unsigned MAX_BITS = 32 >
151.74 +struct Register_block_base;
151.75 +
151.76 +template<>
151.77 +struct Register_block_base<8>
151.78 +{
151.79 + virtual l4_uint8_t do_read_8(l4_addr_t reg) const = 0;
151.80 + virtual void do_write_8(l4_uint8_t value, l4_addr_t reg) = 0;
151.81 + virtual ~Register_block_base() = 0;
151.82 +};
151.83 +
151.84 +inline Register_block_base<8>::~Register_block_base() {}
151.85 +
151.86 +template<>
151.87 +struct Register_block_base<16> : Register_block_base<8>
151.88 +{
151.89 + virtual l4_uint16_t do_read_16(l4_addr_t reg) const = 0;
151.90 + virtual void do_write_16(l4_uint16_t value, l4_addr_t reg) = 0;
151.91 +};
151.92 +
151.93 +template<>
151.94 +struct Register_block_base<32> : Register_block_base<16>
151.95 +{
151.96 + virtual l4_uint32_t do_read_32(l4_addr_t reg) const = 0;
151.97 + virtual void do_write_32(l4_uint32_t value, l4_addr_t reg) = 0;
151.98 +};
151.99 +
151.100 +template<>
151.101 +struct Register_block_base<64> : Register_block_base<32>
151.102 +{
151.103 + virtual l4_uint64_t do_read_64(l4_addr_t reg) const = 0;
151.104 + virtual void do_write_64(l4_uint64_t value, l4_addr_t reg) = 0;
151.105 +};
151.106 +#undef REGBLK_READ_TEMPLATE
151.107 +#undef REGBLK_WRITE_TEMPLATE
151.108 +
151.109 +template<typename CHILD>
151.110 +struct Register_block_modify_mixin
151.111 +{
151.112 + template< typename T >
151.113 + T modify(T clear_bits, T set_bits, l4_addr_t reg) const
151.114 + {
151.115 + CHILD const *c = static_cast<CHILD const *>(this);
151.116 + T r = (c->template read<T>(reg) & ~clear_bits) | set_bits;
151.117 + c->template write<T>(r, reg);
151.118 + return r;
151.119 + }
151.120 +
151.121 + template< typename T >
151.122 + T set(T set_bits, l4_addr_t reg) const
151.123 + { return this->template modify<T>(T(0), set_bits, reg); }
151.124 +
151.125 + template< typename T >
151.126 + T clear(T clear_bits, l4_addr_t reg) const
151.127 + { return this->template modify<T>(clear_bits, T(0), reg); }
151.128 +};
151.129 +
151.130 +
151.131 +#define REGBLK_READ_TEMPLATE(sz) \
151.132 + template< typename T > \
151.133 + typename cxx::enable_if<sizeof(T) == (sz / 8), T>::type read(l4_addr_t reg) const \
151.134 + { \
151.135 + union X { T t; l4_uint##sz##_t v; } m; \
151.136 + m.v = _b->do_read_##sz (reg); \
151.137 + return m.t; \
151.138 + }
151.139 +
151.140 +#define REGBLK_WRITE_TEMPLATE(sz) \
151.141 + template< typename T > \
151.142 + void write(T value, l4_addr_t reg, typename cxx::enable_if<sizeof(T) == (sz / 8), T>::type = T()) const \
151.143 + { \
151.144 + union X { T t; l4_uint##sz##_t v; } m; \
151.145 + m.t = value; \
151.146 + _b->do_write_##sz(m.v, reg); \
151.147 + }
151.148 +
151.149 +/**
151.150 + * \brief Helper template that translates to the Register_block_base
151.151 + * interface.
151.152 + * \tparam BLOCK The type of the Register_block_base interface to use.
151.153 + *
151.154 + * This helper translates read<T>(), write<T>(), set<T>(), clear<T>(),
151.155 + * and modify<T>() calls to BLOCK::do_read_<xx> and BLOCK::do_write_<xx>.
151.156 + */
151.157 +template< typename BLOCK >
151.158 +class Register_block_tmpl
151.159 +: public Register_block_modify_mixin<Register_block_tmpl<BLOCK> >
151.160 +{
151.161 +private:
151.162 + BLOCK *_b;
151.163 +
151.164 +public:
151.165 + Register_block_tmpl(BLOCK *blk) : _b(blk) {}
151.166 + Register_block_tmpl() = default;
151.167 +
151.168 + operator BLOCK * () const { return _b; }
151.169 +
151.170 + REGBLK_READ_TEMPLATE(8)
151.171 + REGBLK_WRITE_TEMPLATE(8)
151.172 + REGBLK_READ_TEMPLATE(16)
151.173 + REGBLK_WRITE_TEMPLATE(16)
151.174 + REGBLK_READ_TEMPLATE(32)
151.175 + REGBLK_WRITE_TEMPLATE(32)
151.176 + REGBLK_READ_TEMPLATE(64)
151.177 + REGBLK_WRITE_TEMPLATE(64)
151.178 +};
151.179 +
151.180 +
151.181 +#undef REGBLK_READ_TEMPLATE
151.182 +#undef REGBLK_WRITE_TEMPLATE
151.183 +
151.184 +namespace __Type_helper {
151.185 + template<unsigned> struct Unsigned;
151.186 + template<> struct Unsigned<8> { typedef l4_uint8_t type; };
151.187 + template<> struct Unsigned<16> { typedef l4_uint16_t type; };
151.188 + template<> struct Unsigned<32> { typedef l4_uint32_t type; };
151.189 + template<> struct Unsigned<64> { typedef l4_uint64_t type; };
151.190 +};
151.191 +
151.192 +
151.193 +/**
151.194 + * \brief Single read only register inside a Register_block_base interface.
151.195 + * \tparam BITS The access with of the register in bits.
151.196 + * \tparam BLOCK The type for the Register_block_base interface.
151.197 + * \note Objects of this type must be used only in temporary contexts
151.198 + * not in global, class, or object scope.
151.199 + *
151.200 + * Allows simple read only access to a hardware register.
151.201 + */
151.202 +template< unsigned BITS, typename BLOCK >
151.203 +class Ro_register_tmpl
151.204 +{
151.205 +protected:
151.206 + BLOCK _b;
151.207 + unsigned _o;
151.208 +
151.209 +public:
151.210 + typedef typename __Type_helper::Unsigned<BITS>::type value_type;
151.211 +
151.212 + Ro_register_tmpl(BLOCK const &blk, unsigned offset) : _b(blk), _o(offset) {}
151.213 + Ro_register_tmpl() = default;
151.214 +
151.215 + /**
151.216 + * \brief read the value from the hardware register.
151.217 + * \return value read from the hardware register.
151.218 + */
151.219 + operator value_type () const
151.220 + { return _b.template read<value_type>(_o); }
151.221 +
151.222 + /**
151.223 + * \brief read the value from the hardware register.
151.224 + * \return value from the hardware register.
151.225 + */
151.226 + value_type read() const
151.227 + { return _b.template read<value_type>(_o); }
151.228 +};
151.229 +
151.230 +
151.231 +/**
151.232 + * \brief Single hardware register inside a Register_block_base interface.
151.233 + * \tparam BITS The access width for the register in bits.
151.234 + * \tparam BLOCK the type of the Register_block_base interface.
151.235 + * \note Objects of this type msut be used only in temporary contexts
151.236 + * not in global, class, or object scope.
151.237 + */
151.238 +template< unsigned BITS, typename BLOCK >
151.239 +class Register_tmpl : public Ro_register_tmpl<BITS, BLOCK>
151.240 +{
151.241 +public:
151.242 + typedef typename Ro_register_tmpl<BITS, BLOCK>::value_type value_type;
151.243 +
151.244 + Register_tmpl(BLOCK const &blk, unsigned offset)
151.245 + : Ro_register_tmpl<BITS, BLOCK>(blk, offset)
151.246 + {}
151.247 +
151.248 + Register_tmpl() = default;
151.249 +
151.250 + /**
151.251 + * \brief write \a val into the hardware register.
151.252 + * \param val the value to write into the hardware register.
151.253 + */
151.254 + Register_tmpl &operator = (value_type val)
151.255 + { this->_b.template write<value_type>(val, this->_o); return *this; }
151.256 +
151.257 + /**
151.258 + * \brief write \a val into the hardware register.
151.259 + * \param val the value to write into the hardware register.
151.260 + */
151.261 + void write(value_type val)
151.262 + { this->_b.template write<value_type>(val, this->_o); }
151.263 +
151.264 + /**
151.265 + * \brief set bits in \a set_bits in the hardware register.
151.266 + * \param set_bits bits to be set within the hardware register.
151.267 + *
151.268 + * This is a read-modify-write function that does a logical or
151.269 + * of the old value from the register with \a set_bits.
151.270 + *
151.271 + * \code
151.272 + * unsigned old_value = read();
151.273 + * write(old_value | set_bits);
151.274 + * \endcode
151.275 + */
151.276 + value_type set(value_type set_bits)
151.277 + { return this->_b.template set<value_type>(set_bits, this->_o); }
151.278 +
151.279 + /**
151.280 + * \brief clears bits in \a clear_bits in the hardware register.
151.281 + * \param clear_bits bits to be cleared within the hardware register.
151.282 + *
151.283 + * This is a read-modify-write function that does a logical and
151.284 + * of the old value from the register with the negated value of
151.285 + * \a clear_bits.
151.286 + *
151.287 + * \code
151.288 + * unsigned old_value = read();
151.289 + * write(old_value & ~clear_bits);
151.290 + * \endcode
151.291 + */
151.292 + value_type clear(value_type clear_bits)
151.293 + { return this->_b.template clear<value_type>(clear_bits, this->_o); }
151.294 +
151.295 + /**
151.296 + * \brief clears bits in \a clear_bits and sets bits in \a set_bits
151.297 + * in the hardware register.
151.298 + * \param clear_bits bits to be cleared within the hardware register.
151.299 + * \param set_bits bits to set in the hardware register.
151.300 + *
151.301 + * This is a read-modify-write function that first does a logical and
151.302 + * of the old value from the register with the negated value of
151.303 + * \a clear_bits and then does a logical or with \a set_bits.
151.304 + *
151.305 + * \code{.c}
151.306 + * unsigned old_value = read();
151.307 + * write((old_value & ~clear_bits) | set_bits);
151.308 + * \endcode
151.309 + */
151.310 + value_type modify(value_type clear_bits, value_type set_bits)
151.311 + { return this->_b.template modify<value_type>(clear_bits, set_bits, this->_o); }
151.312 +};
151.313 +
151.314 +
151.315 +/**
151.316 + * \brief Handles a reference to a register block of the given
151.317 + * maximum access width.
151.318 + * \tparam MAX_BITS Maximum access width for the registers in this
151.319 + * block.
151.320 + * \tparam BLOCK Type implementing the register accesses (read<>(), write<>(),
151.321 + * modify<>(), set<>(), and clear<>()).
151.322 + *
151.323 + * Provides access to registers in this block via r<WIDTH>() and
151.324 + * operator[]().
151.325 + */
151.326 +template<
151.327 + unsigned MAX_BITS,
151.328 + typename BLOCK = Register_block_tmpl<
151.329 + Register_block_base<MAX_BITS>
151.330 + >
151.331 +>
151.332 +class Register_block
151.333 +{
151.334 +private:
151.335 + template< unsigned B, typename BLK > friend class Register_block;
151.336 + template< unsigned B, typename BLK > friend class Ro_register_block;
151.337 + typedef BLOCK Block;
151.338 + Block _b;
151.339 +
151.340 +public:
151.341 + Register_block() = default;
151.342 + Register_block(Block const &blk) : _b(blk) {}
151.343 + Register_block &operator = (Block const &blk)
151.344 + { _b = blk; return *this; }
151.345 +
151.346 + template< unsigned BITS >
151.347 + Register_block(Register_block<BITS> blk) : _b(blk._b) {}
151.348 +
151.349 + typedef Register_tmpl<MAX_BITS, Block> Register;
151.350 + typedef Ro_register_tmpl<MAX_BITS, Block> Ro_register;
151.351 +
151.352 + /**
151.353 + * \brief Read only access to register at offset \a offset.
151.354 + * \tparam BITS the access width in bits for the register.
151.355 + * \param offset The offset of the register within the register file.
151.356 + * \return register object allowing read only access with width \a BITS.
151.357 + */
151.358 + template< unsigned BITS >
151.359 + Ro_register_tmpl<BITS, Block> r(unsigned offset) const
151.360 + { return Ro_register_tmpl<BITS, Block>(this->_b, offset); }
151.361 +
151.362 + /**
151.363 + * \brief Read only access to register at offset \a offset.
151.364 + * \param offset The offset of the register within the register file.
151.365 + * \return register object allowing read only access with width \a MAX_BITS.
151.366 + */
151.367 + Ro_register operator [] (unsigned offset) const
151.368 + { return this->r<MAX_BITS>(offset); }
151.369 +
151.370 +
151.371 + /**
151.372 + * \brief Read/write access to register at offset \a offset.
151.373 + * \tparam BITS the access width in bits for the register.
151.374 + * \param offset The offset of the register within the register file.
151.375 + * \return register object allowing read and write access with width \a BITS.
151.376 + */
151.377 + template< unsigned BITS >
151.378 + Register_tmpl<BITS, Block> r(unsigned offset)
151.379 + { return Register_tmpl<BITS, Block>(this->_b, offset); }
151.380 +
151.381 + /**
151.382 + * \brief Read/write access to register at offset \a offset.
151.383 + * \param offset The offset of the register within the register file.
151.384 + * \return register object allowing read and write access with
151.385 + * width \a MAX_BITS.
151.386 + */
151.387 + Register operator [] (unsigned offset)
151.388 + { return this->r<MAX_BITS>(offset); }
151.389 +};
151.390 +
151.391 +/**
151.392 + * \brief Handles a reference to a read only register block of the given
151.393 + * maximum access width.
151.394 + * \tparam MAX_BITS Maximum access width for the registers in this block.
151.395 + * \tparam BLOCK Type implementing the register accesses (read<>()),
151.396 + *
151.397 + * Provides read only access to registers in this block via r<WIDTH>()
151.398 + * and operator[]().
151.399 + */
151.400 +template<
151.401 + unsigned MAX_BITS,
151.402 + typename BLOCK = Register_block_tmpl<
151.403 + Register_block_base<MAX_BITS> const
151.404 + >
151.405 +>
151.406 +class Ro_register_block
151.407 +{
151.408 +private:
151.409 + template< unsigned B, typename BLK > friend class Ro_register_block;
151.410 + typedef BLOCK Block;
151.411 + Block _b;
151.412 +
151.413 +public:
151.414 + Ro_register_block() = default;
151.415 + Ro_register_block(BLOCK const &blk) : _b(blk) {}
151.416 +
151.417 + template< unsigned BITS >
151.418 + Ro_register_block(Register_block<BITS> const &blk) : _b(blk._b) {}
151.419 +
151.420 + typedef Ro_register_tmpl<MAX_BITS, Block> Ro_register;
151.421 + typedef Ro_register Register;
151.422 +
151.423 + /**
151.424 + * \brief Read only access to register at offset \a offset.
151.425 + * \param offset The offset of the register within the register file.
151.426 + * \return register object allowing read only access with width \a MAX_BITS.
151.427 + */
151.428 + Ro_register operator [] (unsigned offset) const
151.429 + { return Ro_register(this->_b, offset); }
151.430 +
151.431 + /**
151.432 + * \brief Read only access to register at offset \a offset.
151.433 + * \tparam BITS the access width in bits for the register.
151.434 + * \param offset The offset of the register within the register file.
151.435 + * \return register object allowing read only access with width \a BITS.
151.436 + */
151.437 + template< unsigned BITS >
151.438 + Ro_register_tmpl<BITS, Block> r(unsigned offset) const
151.439 + { return Ro_register_tmpl<BITS, Block>(this->_b, offset); }
151.440 +};
151.441 +
151.442 +
151.443 +/**
151.444 + * \brief Implementation helper for register blocks.
151.445 + * \param BASE The class implementing read<> and write<> template functions
151.446 + * for accessing the registers. This class must inherit from
151.447 + * Register_block_impl.
151.448 + * \param MAX_BITS The maximum access width for the register file.
151.449 + * Supported values are 8, 16, 32, or 64.
151.450 + *
151.451 + *
151.452 + * This template allows easy implementation of register files by providing
151.453 + * read<> and write<> template functions, see Mmio_register_block
151.454 + * as an example.
151.455 + */
151.456 +template< typename BASE, unsigned MAX_BITS = 32 >
151.457 +struct Register_block_impl;
151.458 +
151.459 +#define REGBLK_IMPL_RW_TEMPLATE(sz, ...) \
151.460 + l4_uint##sz##_t do_read_##sz(l4_addr_t reg) const \
151.461 + { return static_cast<BASE const *>(this)->template read<l4_uint##sz##_t>(reg); } \
151.462 + \
151.463 + void do_write_##sz(l4_uint##sz##_t value, l4_addr_t reg) \
151.464 + { return static_cast<BASE*>(this)->template write<l4_uint##sz##_t>(value, reg); }
151.465 +
151.466 +
151.467 +template< typename BASE >
151.468 +struct Register_block_impl<BASE, 8> : public Register_block_base<8>
151.469 +{
151.470 + REGBLK_IMPL_RW_TEMPLATE(8);
151.471 +};
151.472 +
151.473 +template< typename BASE >
151.474 +struct Register_block_impl<BASE, 16> : public Register_block_base<16>
151.475 +{
151.476 + REGBLK_IMPL_RW_TEMPLATE(8);
151.477 + REGBLK_IMPL_RW_TEMPLATE(16);
151.478 +};
151.479 +
151.480 +template< typename BASE >
151.481 +struct Register_block_impl<BASE, 32> : public Register_block_base<32>
151.482 +{
151.483 + REGBLK_IMPL_RW_TEMPLATE(8);
151.484 + REGBLK_IMPL_RW_TEMPLATE(16);
151.485 + REGBLK_IMPL_RW_TEMPLATE(32);
151.486 +};
151.487 +
151.488 +template< typename BASE >
151.489 +struct Register_block_impl<BASE, 64> : public Register_block_base<64>
151.490 +{
151.491 + REGBLK_IMPL_RW_TEMPLATE(8);
151.492 + REGBLK_IMPL_RW_TEMPLATE(16);
151.493 + REGBLK_IMPL_RW_TEMPLATE(32);
151.494 + REGBLK_IMPL_RW_TEMPLATE(64);
151.495 +};
151.496 +
151.497 +#undef REGBLK_IMPL_RW_TEMPLATE
151.498 +
151.499 +/** \brief Dummy register block to be used as a placeholder */
151.500 +extern Register_block<64> dummy_register_block;
151.501 +
151.502 +}
152.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
152.2 +++ b/pkg/devices/lib/cpm/Makefile Sun May 13 01:34:16 2018 +0200
152.3 @@ -0,0 +1,8 @@
152.4 +PKGDIR ?= ../..
152.5 +L4DIR ?= $(PKGDIR)/../..
152.6 +
152.7 +TARGET := include src
152.8 +
152.9 +include $(L4DIR)/mk/subdir.mk
152.10 +
152.11 +src: include
153.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
153.2 +++ b/pkg/devices/lib/cpm/include/Makefile Sun May 13 01:34:16 2018 +0200
153.3 @@ -0,0 +1,4 @@
153.4 +PKGDIR = ../../..
153.5 +L4DIR ?= $(PKGDIR)/../..
153.6 +
153.7 +include $(L4DIR)/mk/include.mk
154.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
154.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4730.h Sun May 13 01:34:16 2018 +0200
154.3 @@ -0,0 +1,115 @@
154.4 +/*
154.5 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
154.6 + *
154.7 + * This program is free software; you can redistribute it and/or
154.8 + * modify it under the terms of the GNU General Public License as
154.9 + * published by the Free Software Foundation; either version 2 of
154.10 + * the License, or (at your option) any later version.
154.11 + *
154.12 + * This program is distributed in the hope that it will be useful,
154.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
154.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
154.15 + * GNU General Public License for more details.
154.16 + *
154.17 + * You should have received a copy of the GNU General Public License
154.18 + * along with this program; if not, write to the Free Software
154.19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
154.20 + * Boston, MA 02110-1301, USA
154.21 + */
154.22 +
154.23 +#pragma once
154.24 +
154.25 +#include "cpm.h"
154.26 +
154.27 +#include <l4/sys/types.h>
154.28 +#include <stdint.h>
154.29 +
154.30 +
154.31 +
154.32 +#ifdef __cplusplus
154.33 +
154.34 +#include <l4/devices/hw_register_block.h>
154.35 +
154.36 +/* A simple abstraction for accessing the CPM registers.
154.37 + * A proper device could inherit from Hw::Device and use an
154.38 + * Int_property for _exclk_freq. */
154.39 +
154.40 +class Cpm_jz4730_chip : public Cpm_chip
154.41 +{
154.42 +private:
154.43 + Hw::Register_block<32> _regs;
154.44 + uint32_t _exclk_freq;
154.45 +
154.46 + int pll_enabled();
154.47 + int pll_bypassed();
154.48 +
154.49 +public:
154.50 + Cpm_jz4730_chip(l4_addr_t addr, uint32_t exclk_freq);
154.51 +
154.52 + int have_clock();
154.53 + void start_clock();
154.54 +
154.55 + int have_pll();
154.56 +
154.57 + uint16_t get_multiplier();
154.58 + uint8_t get_input_division();
154.59 + uint8_t get_output_division();
154.60 +
154.61 + uint8_t _get_divider(uint32_t reg, uint32_t mask, uint8_t shift);
154.62 + uint8_t get_cpu_divider();
154.63 + uint8_t get_hclock_divider();
154.64 + uint8_t get_pclock_divider();
154.65 + uint8_t get_memory_divider();
154.66 + uint8_t get_source_divider();
154.67 +
154.68 + uint16_t get_lcd_pixel_divider();
154.69 + uint32_t get_lcd_pixel_frequency();
154.70 +
154.71 + void set_lcd_device_divider(uint8_t division);
154.72 + void set_lcd_pixel_divider(uint16_t division);
154.73 + void set_lcd_frequencies(uint32_t pclk, uint8_t ratio);
154.74 +
154.75 + void start_lcd();
154.76 + void stop_lcd();
154.77 +
154.78 + uint32_t get_pll_frequency();
154.79 + uint32_t get_output_frequency();
154.80 + void update_output_frequency();
154.81 +
154.82 + uint32_t get_cpu_frequency();
154.83 + uint32_t get_hclock_frequency();
154.84 + uint32_t get_pclock_frequency();
154.85 + uint32_t get_memory_frequency();
154.86 +};
154.87 +
154.88 +#endif /* __cplusplus */
154.89 +
154.90 +
154.91 +
154.92 +/* C language interface. */
154.93 +
154.94 +EXTERN_C_BEGIN
154.95 +
154.96 +void *jz4730_cpm_init(l4_addr_t cpm_base);
154.97 +
154.98 +int jz4730_cpm_have_pll(void *cpm);
154.99 +
154.100 +int jz4730_cpm_have_clock(void *cpm);
154.101 +void jz4730_cpm_start_clock(void *cpm);
154.102 +
154.103 +void jz4730_cpm_start_lcd(void *cpm);
154.104 +void jz4730_cpm_stop_lcd(void *cpm);
154.105 +
154.106 +uint16_t jz4730_cpm_get_lcd_pixel_divider(void *cpm);
154.107 +uint32_t jz4730_cpm_get_lcd_pixel_frequency(void *cpm);
154.108 +
154.109 +void jz4730_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio);
154.110 +void jz4730_cpm_update_output_frequency(void *cpm);
154.111 +
154.112 +uint32_t jz4730_cpm_get_cpu_frequency(void *cpm);
154.113 +uint32_t jz4730_cpm_get_hclock_frequency(void *cpm);
154.114 +uint32_t jz4730_cpm_get_output_frequency(void *cpm);
154.115 +uint32_t jz4730_cpm_get_pclock_frequency(void *cpm);
154.116 +uint32_t jz4730_cpm_get_memory_frequency(void *cpm);
154.117 +
154.118 +EXTERN_C_END
155.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
155.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4740.h Sun May 13 01:34:16 2018 +0200
155.3 @@ -0,0 +1,115 @@
155.4 +/*
155.5 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
155.6 + *
155.7 + * This program is free software; you can redistribute it and/or
155.8 + * modify it under the terms of the GNU General Public License as
155.9 + * published by the Free Software Foundation; either version 2 of
155.10 + * the License, or (at your option) any later version.
155.11 + *
155.12 + * This program is distributed in the hope that it will be useful,
155.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
155.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155.15 + * GNU General Public License for more details.
155.16 + *
155.17 + * You should have received a copy of the GNU General Public License
155.18 + * along with this program; if not, write to the Free Software
155.19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
155.20 + * Boston, MA 02110-1301, USA
155.21 + */
155.22 +
155.23 +#pragma once
155.24 +
155.25 +#include "cpm.h"
155.26 +
155.27 +#include <l4/sys/types.h>
155.28 +#include <stdint.h>
155.29 +
155.30 +
155.31 +
155.32 +#ifdef __cplusplus
155.33 +
155.34 +#include <l4/devices/hw_register_block.h>
155.35 +
155.36 +/* A simple abstraction for accessing the CPM registers.
155.37 + * A proper device could inherit from Hw::Device and use an
155.38 + * Int_property for _exclk_freq. */
155.39 +
155.40 +class Cpm_jz4740_chip : public Cpm_chip
155.41 +{
155.42 +private:
155.43 + Hw::Register_block<32> _regs;
155.44 + uint32_t _exclk_freq;
155.45 +
155.46 + int pll_enabled();
155.47 + int pll_bypassed();
155.48 +
155.49 +public:
155.50 + Cpm_jz4740_chip(l4_addr_t addr, uint32_t exclk_freq);
155.51 +
155.52 + int have_clock();
155.53 + void start_clock();
155.54 +
155.55 + int have_pll();
155.56 +
155.57 + uint16_t get_multiplier();
155.58 + uint8_t get_input_division();
155.59 + uint8_t get_output_division();
155.60 +
155.61 + uint8_t _get_divider(uint32_t reg, uint32_t mask, uint8_t shift);
155.62 + uint8_t get_cpu_divider();
155.63 + uint8_t get_hclock_divider();
155.64 + uint8_t get_pclock_divider();
155.65 + uint8_t get_memory_divider();
155.66 + uint8_t get_source_divider();
155.67 +
155.68 + uint16_t get_lcd_pixel_divider();
155.69 + uint32_t get_lcd_pixel_frequency();
155.70 +
155.71 + void set_lcd_device_divider(uint8_t division);
155.72 + void set_lcd_pixel_divider(uint16_t division);
155.73 + void set_lcd_frequencies(uint32_t pclk, uint8_t ratio);
155.74 +
155.75 + void start_lcd();
155.76 + void stop_lcd();
155.77 +
155.78 + uint32_t get_pll_frequency();
155.79 + uint32_t get_output_frequency();
155.80 + void update_output_frequency();
155.81 +
155.82 + uint32_t get_cpu_frequency();
155.83 + uint32_t get_hclock_frequency();
155.84 + uint32_t get_pclock_frequency();
155.85 + uint32_t get_memory_frequency();
155.86 +};
155.87 +
155.88 +#endif /* __cplusplus */
155.89 +
155.90 +
155.91 +
155.92 +/* C language interface. */
155.93 +
155.94 +EXTERN_C_BEGIN
155.95 +
155.96 +void *jz4740_cpm_init(l4_addr_t cpm_base);
155.97 +
155.98 +int jz4740_cpm_have_pll(void *cpm);
155.99 +
155.100 +int jz4740_cpm_have_clock(void *cpm);
155.101 +void jz4740_cpm_start_clock(void *cpm);
155.102 +
155.103 +void jz4740_cpm_start_lcd(void *cpm);
155.104 +void jz4740_cpm_stop_lcd(void *cpm);
155.105 +
155.106 +uint16_t jz4740_cpm_get_lcd_pixel_divider(void *cpm);
155.107 +uint32_t jz4740_cpm_get_lcd_pixel_frequency(void *cpm);
155.108 +
155.109 +void jz4740_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio);
155.110 +void jz4740_cpm_update_output_frequency(void *cpm);
155.111 +
155.112 +uint32_t jz4740_cpm_get_cpu_frequency(void *cpm);
155.113 +uint32_t jz4740_cpm_get_hclock_frequency(void *cpm);
155.114 +uint32_t jz4740_cpm_get_output_frequency(void *cpm);
155.115 +uint32_t jz4740_cpm_get_pclock_frequency(void *cpm);
155.116 +uint32_t jz4740_cpm_get_memory_frequency(void *cpm);
155.117 +
155.118 +EXTERN_C_END
156.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
156.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4780.h Sun May 13 01:34:16 2018 +0200
156.3 @@ -0,0 +1,202 @@
156.4 +/*
156.5 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
156.6 + *
156.7 + * This program is free software; you can redistribute it and/or
156.8 + * modify it under the terms of the GNU General Public License as
156.9 + * published by the Free Software Foundation; either version 2 of
156.10 + * the License, or (at your option) any later version.
156.11 + *
156.12 + * This program is distributed in the hope that it will be useful,
156.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
156.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
156.15 + * GNU General Public License for more details.
156.16 + *
156.17 + * You should have received a copy of the GNU General Public License
156.18 + * along with this program; if not, write to the Free Software
156.19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
156.20 + * Boston, MA 02110-1301, USA
156.21 + */
156.22 +
156.23 +#pragma once
156.24 +
156.25 +#include "cpm.h"
156.26 +
156.27 +#include <l4/sys/types.h>
156.28 +#include <stdint.h>
156.29 +
156.30 +
156.31 +
156.32 +#ifdef __cplusplus
156.33 +
156.34 +#include <l4/devices/hw_register_block.h>
156.35 +
156.36 +/* A simple abstraction for accessing the CPM registers.
156.37 + * A proper device could inherit from Hw::Device and use an
156.38 + * Int_property for _exclk_freq and _rtclk_freq. */
156.39 +
156.40 +class Cpm_jz4780_chip : public Cpm_chip
156.41 +{
156.42 +private:
156.43 + Hw::Register_block<32> _regs;
156.44 + uint32_t _exclk_freq, _rtclk_freq;
156.45 +
156.46 + // Utility methods.
156.47 +
156.48 + uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift);
156.49 + void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value);
156.50 + uint8_t _get_divider(uint32_t reg, uint32_t mask, uint8_t shift);
156.51 +
156.52 + // PLL control.
156.53 +
156.54 + int have_pll(uint32_t pll_reg);
156.55 + int pll_enabled(uint32_t pll_reg);
156.56 + int pll_bypassed(uint32_t pll_reg);
156.57 +
156.58 + // General frequency modifiers.
156.59 +
156.60 + uint16_t get_multiplier(uint32_t pll_reg);
156.61 + void set_multiplier(uint32_t pll_reg, uint16_t multiplier);
156.62 + uint8_t get_input_division(uint32_t pll_reg);
156.63 + void set_input_division(uint32_t pll_reg, uint8_t divider);
156.64 + uint8_t get_output_division(uint32_t pll_reg);
156.65 + void set_output_division(uint32_t pll_reg, uint8_t divider);
156.66 +
156.67 + // Clock dividers.
156.68 +
156.69 + void set_lcd_pixel_divider(uint16_t division);
156.70 +
156.71 + // Clock control.
156.72 +
156.73 + void _update_i2c(uint8_t channel, int enable);
156.74 +
156.75 + // Input frequencies.
156.76 +
156.77 + uint32_t get_pll_frequency(uint32_t pll_reg);
156.78 +
156.79 + // Clock sources.
156.80 +
156.81 + void set_hclock2_source(uint8_t source);
156.82 + void set_lcd_source(uint8_t source);
156.83 +
156.84 +public:
156.85 + void set_pclock_source(uint8_t source);
156.86 + Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq);
156.87 +
156.88 + int have_clock();
156.89 + void start_clock();
156.90 +
156.91 + // Clock divider values.
156.92 +
156.93 + uint8_t get_cpu_divider();
156.94 + uint8_t get_hclock0_divider();
156.95 + uint8_t get_hclock2_divider();
156.96 + uint8_t get_pclock_divider();
156.97 + uint8_t get_lcd_pixel_divider();
156.98 + uint8_t get_memory_divider();
156.99 +
156.100 + // Clock control.
156.101 +
156.102 + void start_lcd();
156.103 + void stop_lcd();
156.104 +
156.105 + void start_i2c(uint8_t channel);
156.106 + void stop_i2c(uint8_t channel);
156.107 +
156.108 + // Input frequencies.
156.109 +
156.110 + uint8_t get_main_source();
156.111 + uint32_t get_main_frequency();
156.112 +
156.113 + // Clock sources, providing the input frequency.
156.114 +
156.115 + uint8_t get_cpu_source();
156.116 + uint8_t get_hclock0_source();
156.117 + uint8_t get_hclock2_source();
156.118 + uint8_t get_lcd_source();
156.119 + uint8_t get_memory_source();
156.120 + uint8_t get_pclock_source();
156.121 +
156.122 + uint32_t get_cpu_source_frequency();
156.123 + uint32_t get_hclock0_source_frequency();
156.124 + uint32_t get_hclock2_source_frequency();
156.125 + uint32_t get_lcd_source_frequency();
156.126 + uint32_t get_memory_source_frequency();
156.127 + uint32_t get_pclock_source_frequency();
156.128 +
156.129 + // Final, calculated frequencies.
156.130 +
156.131 + uint32_t get_cpu_frequency();
156.132 + uint32_t get_hclock0_frequency();
156.133 + uint32_t get_hclock2_frequency();
156.134 + uint32_t get_lcd_pixel_frequency();
156.135 + uint32_t get_memory_frequency();
156.136 + uint32_t get_pclock_frequency();
156.137 +
156.138 + uint32_t get_apll_frequency();
156.139 + uint32_t get_epll_frequency();
156.140 + uint32_t get_mpll_frequency();
156.141 + uint32_t get_vpll_frequency();
156.142 +
156.143 + void set_lcd_pixel_frequency(uint32_t pclk);
156.144 + void set_lcd_frequencies(uint32_t pclk, uint8_t multiplier);
156.145 + void set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider);
156.146 +
156.147 + void update_output_frequency();
156.148 +};
156.149 +
156.150 +#endif /* __cplusplus */
156.151 +
156.152 +
156.153 +
156.154 +/* C language interface. */
156.155 +
156.156 +EXTERN_C_BEGIN
156.157 +
156.158 +void *jz4780_cpm_init(l4_addr_t cpm_base);
156.159 +
156.160 +int jz4780_cpm_have_clock(void *cpm);
156.161 +void jz4780_cpm_start_clock(void *cpm);
156.162 +
156.163 +void jz4780_cpm_start_lcd(void *cpm);
156.164 +void jz4780_cpm_stop_lcd(void *cpm);
156.165 +
156.166 +uint8_t jz4780_cpm_get_cpu_divider(void *cpm);
156.167 +uint8_t jz4780_cpm_get_hclock0_divider(void *cpm);
156.168 +uint8_t jz4780_cpm_get_hclock2_divider(void *cpm);
156.169 +uint8_t jz4780_cpm_get_lcd_pixel_divider(void *cpm);
156.170 +uint8_t jz4780_cpm_get_memory_divider(void *cpm);
156.171 +uint8_t jz4780_cpm_get_pclock_divider(void *cpm);
156.172 +
156.173 +uint8_t jz4780_cpm_get_hclock0_source(void *cpm);
156.174 +uint8_t jz4780_cpm_get_hclock2_source(void *cpm);
156.175 +uint8_t jz4780_cpm_get_lcd_source(void *cpm);
156.176 +uint8_t jz4780_cpm_get_memory_source(void *cpm);
156.177 +uint8_t jz4780_cpm_get_pclock_source(void *cpm);
156.178 +
156.179 +uint32_t jz4780_cpm_get_hclock0_source_frequency(void *cpm);
156.180 +uint32_t jz4780_cpm_get_hclock2_source_frequency(void *cpm);
156.181 +uint32_t jz4780_cpm_get_lcd_source_frequency(void *cpm);
156.182 +uint32_t jz4780_cpm_get_memory_source_frequency(void *cpm);
156.183 +uint32_t jz4780_cpm_get_pclock_source_frequency(void *cpm);
156.184 +
156.185 +void jz4780_cpm_set_pclock_source(void *cpm, uint8_t source);
156.186 +
156.187 +uint8_t jz4780_cpm_get_main_source(void *cpm);
156.188 +uint32_t jz4780_cpm_get_main_frequency(void *cpm);
156.189 +
156.190 +uint32_t jz4780_cpm_get_cpu_frequency(void *cpm);
156.191 +uint32_t jz4780_cpm_get_hclock0_frequency(void *cpm);
156.192 +uint32_t jz4780_cpm_get_hclock2_frequency(void *cpm);
156.193 +uint32_t jz4780_cpm_get_lcd_pixel_frequency(void *cpm);
156.194 +uint32_t jz4780_cpm_get_memory_frequency(void *cpm);
156.195 +uint32_t jz4780_cpm_get_pclock_frequency(void *cpm);
156.196 +
156.197 +uint32_t jz4780_cpm_get_apll_frequency(void *cpm);
156.198 +uint32_t jz4780_cpm_get_epll_frequency(void *cpm);
156.199 +uint32_t jz4780_cpm_get_mpll_frequency(void *cpm);
156.200 +uint32_t jz4780_cpm_get_vpll_frequency(void *cpm);
156.201 +
156.202 +void jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk);
156.203 +void jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider);
156.204 +
156.205 +EXTERN_C_END
157.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
157.2 +++ b/pkg/devices/lib/cpm/include/cpm.h Sun May 13 01:34:16 2018 +0200
157.3 @@ -0,0 +1,44 @@
157.4 +/*
157.5 + * Clock and power management (CPM) abstractions.
157.6 + *
157.7 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
157.8 + *
157.9 + * This program is free software; you can redistribute it and/or
157.10 + * modify it under the terms of the GNU General Public License as
157.11 + * published by the Free Software Foundation; either version 2 of
157.12 + * the License, or (at your option) any later version.
157.13 + *
157.14 + * This program is distributed in the hope that it will be useful,
157.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
157.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
157.17 + * GNU General Public License for more details.
157.18 + *
157.19 + * You should have received a copy of the GNU General Public License
157.20 + * along with this program; if not, write to the Free Software
157.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
157.22 + * Boston, MA 02110-1301, USA
157.23 + */
157.24 +
157.25 +#pragma once
157.26 +
157.27 +#include <l4/sys/types.h>
157.28 +#include <stdint.h>
157.29 +
157.30 +
157.31 +
157.32 +#ifdef __cplusplus
157.33 +
157.34 +/* A simple abstraction for accessing the CPM registers. */
157.35 +
157.36 +class Cpm_chip
157.37 +{
157.38 +public:
157.39 + virtual void set_lcd_frequencies(uint32_t pclk, uint8_t ratio) = 0;
157.40 +
157.41 + virtual void start_lcd() = 0;
157.42 + virtual void stop_lcd() = 0;
157.43 +
157.44 + virtual void update_output_frequency() = 0;
157.45 +};
157.46 +
157.47 +#endif /* __cplusplus */
158.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
158.2 +++ b/pkg/devices/lib/cpm/src/Makefile Sun May 13 01:34:16 2018 +0200
158.3 @@ -0,0 +1,13 @@
158.4 +PKGDIR ?= ../../..
158.5 +L4DIR ?= $(PKGDIR)/../..
158.6 +
158.7 +TARGET = libcpm.o.a
158.8 +PC_FILENAME := libdrivers-cpm
158.9 +
158.10 +SRC_CC := jz4730.cc jz4740.cc jz4780.cc
158.11 +
158.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/cpm/include
158.13 +
158.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common
158.15 +
158.16 +include $(L4DIR)/mk/lib.mk
159.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
159.2 +++ b/pkg/devices/lib/cpm/src/jz4730.cc Sun May 13 01:34:16 2018 +0200
159.3 @@ -0,0 +1,446 @@
159.4 +/*
159.5 + * Clock and power management. This exposes the combined functionality
159.6 + * provided by the jz4730. The power management functionality could be exposed
159.7 + * using a separate driver.
159.8 + *
159.9 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
159.10 + *
159.11 + * This program is free software; you can redistribute it and/or
159.12 + * modify it under the terms of the GNU General Public License as
159.13 + * published by the Free Software Foundation; either version 2 of
159.14 + * the License, or (at your option) any later version.
159.15 + *
159.16 + * This program is distributed in the hope that it will be useful,
159.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
159.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
159.19 + * GNU General Public License for more details.
159.20 + *
159.21 + * You should have received a copy of the GNU General Public License
159.22 + * along with this program; if not, write to the Free Software
159.23 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
159.24 + * Boston, MA 02110-1301, USA
159.25 + */
159.26 +
159.27 +#include <l4/devices/hw_mmio_register_block.h>
159.28 +#include "cpm-jz4730.h"
159.29 +
159.30 +
159.31 +
159.32 +enum Regs : unsigned
159.33 +{
159.34 + Clock_control = 0x000, // CFCR (CPCCR in JZ4740)
159.35 + Pll_control = 0x010, // PLCR1 (CPPCR in JZ4740)
159.36 + Clock_gate = 0x020, // MSCR (CLKGR in JZ4740)
159.37 + Sleep_control = 0x024, // SCR
159.38 + Lcd_divider = 0x060, // CFCR2
159.39 +};
159.40 +
159.41 +enum Clock_bits : unsigned
159.42 +{
159.43 + Clock_enable = 20, // UPE
159.44 + Clock_memory_divider = 16, // MFR
159.45 + Clock_lcd_divider = 12, // LFR
159.46 + Clock_pclock_divider = 8, // PFR (slow APB peripherals)
159.47 + Clock_hclock_divider = 4, // SFR (fast AHB peripherals)
159.48 + Clock_cpu_divider = 0, // IFR
159.49 +};
159.50 +
159.51 +enum Pll_bits : unsigned
159.52 +{
159.53 + Pll_multiplier = 23, // PLL1FD
159.54 + Pll_input_division = 18, // PLL1RD
159.55 + Pll_output_division = 16, // PLL1OD
159.56 + Pll_stable = 10, // PLL1S
159.57 + Pll_bypassed = 9, // PLL1BP
159.58 + Pll_enabled = 8, // PLL1EN
159.59 +};
159.60 +
159.61 +enum Clock_gate_bits : unsigned
159.62 +{
159.63 + Clock_gate_lcd = 7, // LCD
159.64 + Clock_gate_timer = 3, // OST
159.65 +};
159.66 +
159.67 +enum Lcd_divider_bits : unsigned
159.68 +{
159.69 + Lcd_divider_value = 0, // PIXFR (in CFCR2)
159.70 +};
159.71 +
159.72 +
159.73 +
159.74 +// If implemented as a Hw::Device, various properties would be
159.75 +// initialised in the constructor and obtained from the device tree
159.76 +// definitions.
159.77 +
159.78 +Cpm_jz4730_chip::Cpm_jz4730_chip(l4_addr_t addr, uint32_t exclk_freq)
159.79 +: _exclk_freq(exclk_freq)
159.80 +{
159.81 + _regs = new Hw::Mmio_register_block<32>(addr);
159.82 +
159.83 + // add_cid("cpm");
159.84 + // add_cid("cpm-jz4730");
159.85 + // register_property("exclk_freq", &_exclk_freq);
159.86 +}
159.87 +
159.88 +// Clock/timer control.
159.89 +
159.90 +int
159.91 +Cpm_jz4730_chip::have_clock()
159.92 +{
159.93 + return !(_regs[Clock_gate] & (1 << Clock_gate_timer));
159.94 +}
159.95 +
159.96 +void
159.97 +Cpm_jz4730_chip::start_clock()
159.98 +{
159.99 + _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer);
159.100 +}
159.101 +
159.102 +// PLL control.
159.103 +
159.104 +// Return whether the PLL is stable.
159.105 +
159.106 +int
159.107 +Cpm_jz4730_chip::have_pll()
159.108 +{
159.109 + return _regs[Pll_control] & (1 << Pll_stable);
159.110 +}
159.111 +
159.112 +int
159.113 +Cpm_jz4730_chip::pll_enabled()
159.114 +{
159.115 + return _regs[Pll_control] & (1 << Pll_enabled);
159.116 +}
159.117 +
159.118 +int
159.119 +Cpm_jz4730_chip::pll_bypassed()
159.120 +{
159.121 + return _regs[Pll_control] & (1 << Pll_bypassed);
159.122 +}
159.123 +
159.124 +// Feedback (9-bit) multiplier.
159.125 +
159.126 +uint16_t
159.127 +Cpm_jz4730_chip::get_multiplier()
159.128 +{
159.129 + return ((_regs[Pll_control] & (0x1ff << Pll_multiplier)) >> Pll_multiplier) + 2;
159.130 +}
159.131 +
159.132 +// Input (5-bit) divider.
159.133 +
159.134 +uint8_t
159.135 +Cpm_jz4730_chip::get_input_division()
159.136 +{
159.137 + return ((_regs[Pll_control] & (0x1f << Pll_input_division)) >> Pll_input_division) + 2;
159.138 +}
159.139 +
159.140 +// Output divider.
159.141 +
159.142 +static uint8_t od[4] = {1, 2, 2, 4};
159.143 +
159.144 +uint8_t
159.145 +Cpm_jz4730_chip::get_output_division()
159.146 +{
159.147 + return od[(_regs[Pll_control] & (0x03 << Pll_output_division)) >> Pll_output_division];
159.148 +}
159.149 +
159.150 +// General clock divider.
159.151 +
159.152 +static uint8_t cd[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
159.153 +
159.154 +uint8_t
159.155 +Cpm_jz4730_chip::_get_divider(uint32_t reg, uint32_t mask, uint8_t shift)
159.156 +{
159.157 + uint8_t d = (_regs[reg] & mask) >> shift;
159.158 + return (d < 10) ? cd[d] : 1;
159.159 +}
159.160 +
159.161 +// CPU clock (CCLK) divider.
159.162 +
159.163 +uint8_t
159.164 +Cpm_jz4730_chip::get_cpu_divider()
159.165 +{
159.166 + return _get_divider(Clock_control, 0xf << Clock_cpu_divider, Clock_cpu_divider);
159.167 +}
159.168 +
159.169 +// Fast peripheral clock (HCLK) divider.
159.170 +
159.171 +uint8_t
159.172 +Cpm_jz4730_chip::get_hclock_divider()
159.173 +{
159.174 + return _get_divider(Clock_control, 0xf << Clock_hclock_divider, Clock_hclock_divider);
159.175 +}
159.176 +
159.177 +// Slow peripheral clock (PCLK) divider.
159.178 +
159.179 +uint8_t
159.180 +Cpm_jz4730_chip::get_pclock_divider()
159.181 +{
159.182 + return _get_divider(Clock_control, 0xf << Clock_pclock_divider, Clock_pclock_divider);
159.183 +}
159.184 +
159.185 +// Memory clock (MCLK) divider.
159.186 +
159.187 +uint8_t
159.188 +Cpm_jz4730_chip::get_memory_divider()
159.189 +{
159.190 + return _get_divider(Clock_control, 0xf << Clock_memory_divider, Clock_memory_divider);
159.191 +}
159.192 +
159.193 +// Clock source divider for MSC, I2S, LCD and USB.
159.194 +
159.195 +uint8_t
159.196 +Cpm_jz4730_chip::get_source_divider()
159.197 +{
159.198 + return 1;
159.199 +}
159.200 +
159.201 +// LCD device clock divider.
159.202 +
159.203 +void
159.204 +Cpm_jz4730_chip::set_lcd_device_divider(uint8_t division)
159.205 +{
159.206 + if (division == 0)
159.207 + division = 1;
159.208 +
159.209 + // NOTE: The vendor code (clock.c) bounds the divider at 16, but maybe this is
159.210 + // NOTE: confused with the width of the bitfield which actually contains an
159.211 + // NOTE: index for the clock divider value array (cd).
159.212 +
159.213 + else if (division > 16)
159.214 + division = 16;
159.215 +
159.216 + // Obtain the divider or closest higher divider.
159.217 +
159.218 + int i;
159.219 +
159.220 + for (i = 0; i < 10; i++)
159.221 + if (cd[i] >= division) break;
159.222 +
159.223 + _regs[Clock_control] = (_regs[Clock_control] & ~(0xf << Clock_lcd_divider)) |
159.224 + (cd[i] << Clock_lcd_divider);
159.225 +}
159.226 +
159.227 +// LCD pixel clock divider.
159.228 +
159.229 +uint16_t
159.230 +Cpm_jz4730_chip::get_lcd_pixel_divider()
159.231 +{
159.232 + return (_regs[Lcd_divider] >> Lcd_divider_value) + 1;
159.233 +}
159.234 +
159.235 +void
159.236 +Cpm_jz4730_chip::set_lcd_pixel_divider(uint16_t division)
159.237 +{
159.238 + if (division == 0)
159.239 + division = 1;
159.240 + else if (division > 512)
159.241 + division = 512;
159.242 +
159.243 + _regs[Lcd_divider] = (_regs[Lcd_divider] & ~(0x1ff << Lcd_divider_value)) |
159.244 + ((division - 1) << Lcd_divider_value);
159.245 +}
159.246 +
159.247 +
159.248 +
159.249 +uint32_t
159.250 +Cpm_jz4730_chip::get_lcd_pixel_frequency()
159.251 +{
159.252 + return get_output_frequency() / get_lcd_pixel_divider();
159.253 +}
159.254 +
159.255 +// Set the device and pixel frequencies, indicating the latter and
159.256 +// providing the device:pixel frequency ratio.
159.257 +
159.258 +void
159.259 +Cpm_jz4730_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio)
159.260 +{
159.261 + uint32_t out = get_output_frequency(),
159.262 + lcd = pclk * ratio;
159.263 +
159.264 + set_lcd_pixel_divider(out / pclk);
159.265 +
159.266 + // Limit the device frequency to 150MHz.
159.267 +
159.268 + if (lcd > 150000000) lcd = 150000000;
159.269 +
159.270 + set_lcd_device_divider(out / lcd);
159.271 +}
159.272 +
159.273 +
159.274 +
159.275 +// LCD clock control.
159.276 +
159.277 +void
159.278 +Cpm_jz4730_chip::start_lcd()
159.279 +{
159.280 + _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_lcd);
159.281 +}
159.282 +
159.283 +void
159.284 +Cpm_jz4730_chip::stop_lcd()
159.285 +{
159.286 + _regs[Clock_gate] = _regs[Clock_gate] | (1 << Clock_gate_lcd);
159.287 +}
159.288 +
159.289 +
159.290 +
159.291 +uint32_t
159.292 +Cpm_jz4730_chip::get_pll_frequency()
159.293 +{
159.294 + // Test for PLL enable and not PLL bypass.
159.295 +
159.296 + if (pll_enabled() && !pll_bypassed())
159.297 + return (_exclk_freq * get_multiplier()) /
159.298 + (get_input_division() * get_output_division());
159.299 + else
159.300 + return _exclk_freq;
159.301 +}
159.302 +
159.303 +// Clock frequency for MSC, I2S, LCD and USB.
159.304 +
159.305 +uint32_t
159.306 +Cpm_jz4730_chip::get_output_frequency()
159.307 +{
159.308 + return get_pll_frequency() / get_source_divider();
159.309 +}
159.310 +
159.311 +void
159.312 +Cpm_jz4730_chip::update_output_frequency()
159.313 +{
159.314 + _regs[Clock_control] = _regs[Clock_control] | (1 << Clock_enable);
159.315 +}
159.316 +
159.317 +// Clock frequency for the CPU.
159.318 +
159.319 +uint32_t Cpm_jz4730_chip::get_cpu_frequency()
159.320 +{
159.321 + if (pll_enabled())
159.322 + return get_pll_frequency() / get_cpu_divider();
159.323 + else
159.324 + return _exclk_freq;
159.325 +}
159.326 +
159.327 +// Clock frequency for fast peripherals.
159.328 +
159.329 +uint32_t
159.330 +Cpm_jz4730_chip::get_hclock_frequency()
159.331 +{
159.332 + if (pll_enabled())
159.333 + return get_pll_frequency() / get_hclock_divider();
159.334 + else
159.335 + return _exclk_freq;
159.336 +}
159.337 +
159.338 +// Clock frequency for slow peripherals.
159.339 +
159.340 +uint32_t
159.341 +Cpm_jz4730_chip::get_pclock_frequency()
159.342 +{
159.343 + if (pll_enabled())
159.344 + return get_pll_frequency() / get_pclock_divider();
159.345 + else
159.346 + return _exclk_freq;
159.347 +}
159.348 +
159.349 +// Clock frequency for the memory.
159.350 +
159.351 +uint32_t
159.352 +Cpm_jz4730_chip::get_memory_frequency()
159.353 +{
159.354 + if (pll_enabled())
159.355 + return get_pll_frequency() / get_memory_divider();
159.356 + else
159.357 + return _exclk_freq;
159.358 +}
159.359 +
159.360 +
159.361 +
159.362 +// C language interface functions.
159.363 +
159.364 +void
159.365 +*jz4730_cpm_init(l4_addr_t cpm_base)
159.366 +{
159.367 + /* Initialise the clock and power management peripheral with the
159.368 + register memory region and a 3.6864 MHz EXCLK frequency. */
159.369 +
159.370 + return (void *) new Cpm_jz4730_chip(cpm_base, 3686400);
159.371 +}
159.372 +
159.373 +int
159.374 +jz4730_cpm_have_clock(void *cpm)
159.375 +{
159.376 + return static_cast<Cpm_jz4730_chip *>(cpm)->have_clock();
159.377 +}
159.378 +
159.379 +void
159.380 +jz4730_cpm_start_clock(void *cpm)
159.381 +{
159.382 + static_cast<Cpm_jz4730_chip *>(cpm)->start_clock();
159.383 +}
159.384 +
159.385 +void
159.386 +jz4730_cpm_start_lcd(void *cpm)
159.387 +{
159.388 + static_cast<Cpm_jz4730_chip *>(cpm)->start_lcd();
159.389 +}
159.390 +
159.391 +void
159.392 +jz4730_cpm_stop_lcd(void *cpm)
159.393 +{
159.394 + static_cast<Cpm_jz4730_chip *>(cpm)->stop_lcd();
159.395 +}
159.396 +
159.397 +uint32_t
159.398 +jz4730_cpm_get_cpu_frequency(void *cpm)
159.399 +{
159.400 + return static_cast<Cpm_jz4730_chip *>(cpm)->get_cpu_frequency();
159.401 +}
159.402 +
159.403 +uint32_t
159.404 +jz4730_cpm_get_hclock_frequency(void *cpm)
159.405 +{
159.406 + return static_cast<Cpm_jz4730_chip *>(cpm)->get_hclock_frequency();
159.407 +}
159.408 +
159.409 +uint32_t
159.410 +jz4730_cpm_get_output_frequency(void *cpm)
159.411 +{
159.412 + return static_cast<Cpm_jz4730_chip *>(cpm)->get_output_frequency();
159.413 +}
159.414 +
159.415 +uint32_t
159.416 +jz4730_cpm_get_pclock_frequency(void *cpm)
159.417 +{
159.418 + return static_cast<Cpm_jz4730_chip *>(cpm)->get_pclock_frequency();
159.419 +}
159.420 +
159.421 +uint32_t
159.422 +jz4730_cpm_get_memory_frequency(void *cpm)
159.423 +{
159.424 + return static_cast<Cpm_jz4730_chip *>(cpm)->get_memory_frequency();
159.425 +}
159.426 +
159.427 +uint16_t
159.428 +jz4730_cpm_get_lcd_pixel_divider(void *cpm)
159.429 +{
159.430 + return static_cast<Cpm_jz4730_chip *>(cpm)->get_lcd_pixel_divider();
159.431 +}
159.432 +
159.433 +uint32_t
159.434 +jz4730_cpm_get_lcd_pixel_frequency(void *cpm)
159.435 +{
159.436 + return static_cast<Cpm_jz4730_chip *>(cpm)->get_lcd_pixel_frequency();
159.437 +}
159.438 +
159.439 +void
159.440 +jz4730_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio)
159.441 +{
159.442 + static_cast<Cpm_jz4730_chip *>(cpm)->set_lcd_frequencies(pclk, ratio);
159.443 +}
159.444 +
159.445 +void
159.446 +jz4730_cpm_update_output_frequency(void *cpm)
159.447 +{
159.448 + static_cast<Cpm_jz4730_chip *>(cpm)->update_output_frequency();
159.449 +}
160.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
160.2 +++ b/pkg/devices/lib/cpm/src/jz4740.cc Sun May 13 01:34:16 2018 +0200
160.3 @@ -0,0 +1,426 @@
160.4 +/*
160.5 + * Clock and power management. This exposes the combined functionality
160.6 + * provided by the jz4740 and related SoCs. The power management
160.7 + * functionality could be exposed using a separate driver.
160.8 + *
160.9 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
160.10 + *
160.11 + * This program is free software; you can redistribute it and/or
160.12 + * modify it under the terms of the GNU General Public License as
160.13 + * published by the Free Software Foundation; either version 2 of
160.14 + * the License, or (at your option) any later version.
160.15 + *
160.16 + * This program is distributed in the hope that it will be useful,
160.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
160.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
160.19 + * GNU General Public License for more details.
160.20 + *
160.21 + * You should have received a copy of the GNU General Public License
160.22 + * along with this program; if not, write to the Free Software
160.23 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
160.24 + * Boston, MA 02110-1301, USA
160.25 + */
160.26 +
160.27 +#include <l4/devices/hw_mmio_register_block.h>
160.28 +#include "cpm-jz4740.h"
160.29 +
160.30 +
160.31 +
160.32 +enum Regs : unsigned
160.33 +{
160.34 + Clock_control = 0x000, // CPCCR
160.35 + Low_power_control = 0x004, // LCR
160.36 + Pll_control = 0x010, // CPPCR
160.37 + Clock_gate = 0x020, // CLKGR
160.38 + Sleep_control = 0x024, // SCR
160.39 + I2s_divider = 0x060, // I2SCDR
160.40 + Lcd_divider = 0x064, // LPCDR
160.41 + Msc_divider = 0x068, // MSCCDR
160.42 + Uhc_divider = 0x06c, // UHCCDR
160.43 + Ssi_divider = 0x074, // SSICDR
160.44 +};
160.45 +
160.46 +enum Clock_bits : unsigned
160.47 +{
160.48 + Clock_enable = 22, // CE
160.49 + Clock_pllout_source = 21, // PCS
160.50 + Clock_lcd_divider = 16, // LCD
160.51 + Clock_memory_divider = 12, // MDIV
160.52 + Clock_pclock_divider = 8, // PDIV (slow APB peripherals)
160.53 + Clock_hclock_divider = 4, // HDIV (fast AHB peripherals)
160.54 + Clock_cpu_divider = 0, // CDIV
160.55 +};
160.56 +
160.57 +enum Pll_bits : unsigned
160.58 +{
160.59 + Pll_multiplier = 23, // PLLM
160.60 + Pll_input_division = 18, // PLLN
160.61 + Pll_output_division = 16, // PLLOD
160.62 + Pll_stable = 10, // PLLS
160.63 + Pll_bypassed = 9, // PLLBP
160.64 + Pll_enabled = 8, // PLLEN
160.65 +};
160.66 +
160.67 +enum Clock_gate_bits : unsigned
160.68 +{
160.69 + Clock_gate_lcd = 10, // LCD
160.70 + Clock_gate_timer = 1, // TCU
160.71 +};
160.72 +
160.73 +enum Lcd_divider_bits : unsigned
160.74 +{
160.75 + Lcd_divider_value = 0,
160.76 +};
160.77 +
160.78 +
160.79 +
160.80 +// If implemented as a Hw::Device, various properties would be
160.81 +// initialised in the constructor and obtained from the device tree
160.82 +// definitions.
160.83 +
160.84 +Cpm_jz4740_chip::Cpm_jz4740_chip(l4_addr_t addr, uint32_t exclk_freq)
160.85 +: _exclk_freq(exclk_freq)
160.86 +{
160.87 + _regs = new Hw::Mmio_register_block<32>(addr);
160.88 +
160.89 + // add_cid("cpm");
160.90 + // add_cid("cpm-jz4740");
160.91 + // register_property("exclk_freq", &_exclk_freq);
160.92 +}
160.93 +
160.94 +// Clock/timer control.
160.95 +
160.96 +int
160.97 +Cpm_jz4740_chip::have_clock()
160.98 +{
160.99 + return !(_regs[Clock_gate] & (1 << Clock_gate_timer));
160.100 +}
160.101 +
160.102 +void
160.103 +Cpm_jz4740_chip::start_clock()
160.104 +{
160.105 + _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer);
160.106 +}
160.107 +
160.108 +// PLL control.
160.109 +
160.110 +// Return whether the PLL is stable.
160.111 +
160.112 +int
160.113 +Cpm_jz4740_chip::have_pll()
160.114 +{
160.115 + return _regs[Pll_control] & (1 << Pll_stable);
160.116 +}
160.117 +
160.118 +int
160.119 +Cpm_jz4740_chip::pll_enabled()
160.120 +{
160.121 + return _regs[Pll_control] & (1 << Pll_enabled);
160.122 +}
160.123 +
160.124 +int
160.125 +Cpm_jz4740_chip::pll_bypassed()
160.126 +{
160.127 + return _regs[Pll_control] & (1 << Pll_bypassed);
160.128 +}
160.129 +
160.130 +// Feedback (9-bit) multiplier.
160.131 +
160.132 +uint16_t
160.133 +Cpm_jz4740_chip::get_multiplier()
160.134 +{
160.135 + return ((_regs[Pll_control] & (0x1ff << Pll_multiplier)) >> Pll_multiplier) + 2;
160.136 +}
160.137 +
160.138 +// Input (5-bit) divider.
160.139 +
160.140 +uint8_t
160.141 +Cpm_jz4740_chip::get_input_division()
160.142 +{
160.143 + return ((_regs[Pll_control] & (0x1f << Pll_input_division)) >> Pll_input_division) + 2;
160.144 +}
160.145 +
160.146 +// Output divider.
160.147 +
160.148 +uint8_t
160.149 +Cpm_jz4740_chip::get_output_division()
160.150 +{
160.151 + uint8_t od[4] = {1, 2, 2, 4};
160.152 + return od[(_regs[Pll_control] & (0x03 << Pll_output_division)) >> Pll_output_division];
160.153 +}
160.154 +
160.155 +// General clock divider.
160.156 +
160.157 +uint8_t
160.158 +Cpm_jz4740_chip::_get_divider(uint32_t reg, uint32_t mask, uint8_t shift)
160.159 +{
160.160 + uint8_t cd[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
160.161 + uint8_t d = (_regs[reg] & mask) >> shift;
160.162 + return (d < 10) ? cd[d] : 1;
160.163 +}
160.164 +
160.165 +// CPU clock (CCLK) divider.
160.166 +
160.167 +uint8_t
160.168 +Cpm_jz4740_chip::get_cpu_divider()
160.169 +{
160.170 + return _get_divider(Clock_control, 0xf << Clock_cpu_divider, Clock_cpu_divider);
160.171 +}
160.172 +
160.173 +// Fast peripheral clock (HCLK) divider.
160.174 +
160.175 +uint8_t
160.176 +Cpm_jz4740_chip::get_hclock_divider()
160.177 +{
160.178 + return _get_divider(Clock_control, 0xf << Clock_hclock_divider, Clock_hclock_divider);
160.179 +}
160.180 +
160.181 +// Slow peripheral clock (PCLK) divider.
160.182 +
160.183 +uint8_t
160.184 +Cpm_jz4740_chip::get_pclock_divider()
160.185 +{
160.186 + return _get_divider(Clock_control, 0xf << Clock_pclock_divider, Clock_pclock_divider);
160.187 +}
160.188 +
160.189 +// Memory clock (MCLK) divider.
160.190 +
160.191 +uint8_t
160.192 +Cpm_jz4740_chip::get_memory_divider()
160.193 +{
160.194 + return _get_divider(Clock_control, 0xf << Clock_memory_divider, Clock_memory_divider);
160.195 +}
160.196 +
160.197 +// Clock source divider for MSC, I2S, LCD and USB.
160.198 +
160.199 +uint8_t
160.200 +Cpm_jz4740_chip::get_source_divider()
160.201 +{
160.202 + return _regs[Clock_control] & (1 << Clock_pllout_source) ? 1 : 2;
160.203 +}
160.204 +
160.205 +// LCD device clock divider.
160.206 +
160.207 +void
160.208 +Cpm_jz4740_chip::set_lcd_device_divider(uint8_t division)
160.209 +{
160.210 + if (division == 0)
160.211 + division = 1;
160.212 + else if (division > 32)
160.213 + division = 32;
160.214 +
160.215 + _regs[Clock_control] = (_regs[Clock_control] & ~(0x1f << Clock_lcd_divider)) |
160.216 + ((division - 1) << Clock_lcd_divider);
160.217 +}
160.218 +
160.219 +// LCD pixel clock divider.
160.220 +
160.221 +uint16_t
160.222 +Cpm_jz4740_chip::get_lcd_pixel_divider()
160.223 +{
160.224 + return (_regs[Lcd_divider] >> Lcd_divider_value) + 1;
160.225 +}
160.226 +
160.227 +void
160.228 +Cpm_jz4740_chip::set_lcd_pixel_divider(uint16_t division)
160.229 +{
160.230 + if (division == 0)
160.231 + division = 1;
160.232 + else if (division > 2048)
160.233 + division = 2048;
160.234 +
160.235 + _regs[Lcd_divider] = (_regs[Lcd_divider] & ~(0x7ff << Lcd_divider_value)) |
160.236 + ((division - 1) << Lcd_divider_value);
160.237 +}
160.238 +
160.239 +
160.240 +
160.241 +uint32_t
160.242 +Cpm_jz4740_chip::get_lcd_pixel_frequency()
160.243 +{
160.244 + return get_output_frequency() / get_lcd_pixel_divider();
160.245 +}
160.246 +
160.247 +// Set the device and pixel frequencies, indicating the latter and
160.248 +// providing the device:pixel frequency ratio.
160.249 +
160.250 +void
160.251 +Cpm_jz4740_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio)
160.252 +{
160.253 + uint32_t out = get_output_frequency(),
160.254 + lcd = pclk * ratio;
160.255 +
160.256 + set_lcd_pixel_divider(out / pclk);
160.257 +
160.258 + // Limit the device frequency to 150MHz.
160.259 +
160.260 + if (lcd > 150000000) lcd = 150000000;
160.261 +
160.262 + set_lcd_device_divider(out / lcd);
160.263 +}
160.264 +
160.265 +
160.266 +
160.267 +// LCD clock control.
160.268 +
160.269 +void
160.270 +Cpm_jz4740_chip::start_lcd()
160.271 +{
160.272 + _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_lcd);
160.273 +}
160.274 +
160.275 +void
160.276 +Cpm_jz4740_chip::stop_lcd()
160.277 +{
160.278 + _regs[Clock_gate] = _regs[Clock_gate] | (1 << Clock_gate_lcd);
160.279 +}
160.280 +
160.281 +
160.282 +
160.283 +uint32_t
160.284 +Cpm_jz4740_chip::get_pll_frequency()
160.285 +{
160.286 + // Test for PLL enable and not PLL bypass.
160.287 +
160.288 + if (pll_enabled() && !pll_bypassed())
160.289 + return (_exclk_freq * get_multiplier()) /
160.290 + (get_input_division() * get_output_division());
160.291 + else
160.292 + return _exclk_freq;
160.293 +}
160.294 +
160.295 +// Clock frequency for MSC, I2S, LCD and USB.
160.296 +
160.297 +uint32_t
160.298 +Cpm_jz4740_chip::get_output_frequency()
160.299 +{
160.300 + return get_pll_frequency() / get_source_divider();
160.301 +}
160.302 +
160.303 +void
160.304 +Cpm_jz4740_chip::update_output_frequency()
160.305 +{
160.306 + _regs[Clock_control] = _regs[Clock_control] | (1 << Clock_enable);
160.307 +}
160.308 +
160.309 +// Clock frequency for the CPU.
160.310 +
160.311 +uint32_t Cpm_jz4740_chip::get_cpu_frequency()
160.312 +{
160.313 + return get_pll_frequency() / get_cpu_divider();
160.314 +}
160.315 +
160.316 +// Clock frequency for fast peripherals.
160.317 +
160.318 +uint32_t
160.319 +Cpm_jz4740_chip::get_hclock_frequency()
160.320 +{
160.321 + return get_pll_frequency() / get_hclock_divider();
160.322 +}
160.323 +
160.324 +// Clock frequency for slow peripherals.
160.325 +
160.326 +uint32_t
160.327 +Cpm_jz4740_chip::get_pclock_frequency()
160.328 +{
160.329 + return get_pll_frequency() / get_pclock_divider();
160.330 +}
160.331 +
160.332 +// Clock frequency for the memory.
160.333 +
160.334 +uint32_t
160.335 +Cpm_jz4740_chip::get_memory_frequency()
160.336 +{
160.337 + return get_pll_frequency() / get_memory_divider();
160.338 +}
160.339 +
160.340 +
160.341 +
160.342 +// C language interface functions.
160.343 +
160.344 +void
160.345 +*jz4740_cpm_init(l4_addr_t cpm_base)
160.346 +{
160.347 + /* Initialise the clock and power management peripheral with the
160.348 + register memory region and a 12MHz EXCLK frequency. */
160.349 +
160.350 + return (void *) new Cpm_jz4740_chip(cpm_base, 12000000);
160.351 +}
160.352 +
160.353 +int
160.354 +jz4740_cpm_have_clock(void *cpm)
160.355 +{
160.356 + return static_cast<Cpm_jz4740_chip *>(cpm)->have_clock();
160.357 +}
160.358 +
160.359 +void
160.360 +jz4740_cpm_start_clock(void *cpm)
160.361 +{
160.362 + static_cast<Cpm_jz4740_chip *>(cpm)->start_clock();
160.363 +}
160.364 +
160.365 +void
160.366 +jz4740_cpm_start_lcd(void *cpm)
160.367 +{
160.368 + static_cast<Cpm_jz4740_chip *>(cpm)->start_lcd();
160.369 +}
160.370 +
160.371 +void
160.372 +jz4740_cpm_stop_lcd(void *cpm)
160.373 +{
160.374 + static_cast<Cpm_jz4740_chip *>(cpm)->stop_lcd();
160.375 +}
160.376 +
160.377 +uint32_t
160.378 +jz4740_cpm_get_cpu_frequency(void *cpm)
160.379 +{
160.380 + return static_cast<Cpm_jz4740_chip *>(cpm)->get_cpu_frequency();
160.381 +}
160.382 +
160.383 +uint32_t
160.384 +jz4740_cpm_get_hclock_frequency(void *cpm)
160.385 +{
160.386 + return static_cast<Cpm_jz4740_chip *>(cpm)->get_hclock_frequency();
160.387 +}
160.388 +
160.389 +uint32_t
160.390 +jz4740_cpm_get_output_frequency(void *cpm)
160.391 +{
160.392 + return static_cast<Cpm_jz4740_chip *>(cpm)->get_output_frequency();
160.393 +}
160.394 +
160.395 +uint32_t
160.396 +jz4740_cpm_get_pclock_frequency(void *cpm)
160.397 +{
160.398 + return static_cast<Cpm_jz4740_chip *>(cpm)->get_pclock_frequency();
160.399 +}
160.400 +
160.401 +uint32_t
160.402 +jz4740_cpm_get_memory_frequency(void *cpm)
160.403 +{
160.404 + return static_cast<Cpm_jz4740_chip *>(cpm)->get_memory_frequency();
160.405 +}
160.406 +
160.407 +uint16_t
160.408 +jz4740_cpm_get_lcd_pixel_divider(void *cpm)
160.409 +{
160.410 + return static_cast<Cpm_jz4740_chip *>(cpm)->get_lcd_pixel_divider();
160.411 +}
160.412 +
160.413 +uint32_t
160.414 +jz4740_cpm_get_lcd_pixel_frequency(void *cpm)
160.415 +{
160.416 + return static_cast<Cpm_jz4740_chip *>(cpm)->get_lcd_pixel_frequency();
160.417 +}
160.418 +
160.419 +void
160.420 +jz4740_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio)
160.421 +{
160.422 + static_cast<Cpm_jz4740_chip *>(cpm)->set_lcd_frequencies(pclk, ratio);
160.423 +}
160.424 +
160.425 +void
160.426 +jz4740_cpm_update_output_frequency(void *cpm)
160.427 +{
160.428 + static_cast<Cpm_jz4740_chip *>(cpm)->update_output_frequency();
160.429 +}
161.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
161.2 +++ b/pkg/devices/lib/cpm/src/jz4780.cc Sun May 13 01:34:16 2018 +0200
161.3 @@ -0,0 +1,918 @@
161.4 +/*
161.5 + * Clock and power management. This exposes the combined functionality
161.6 + * provided by the jz4780 and related SoCs. The power management
161.7 + * functionality could be exposed using a separate driver.
161.8 + *
161.9 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
161.10 + *
161.11 + * This program is free software; you can redistribute it and/or
161.12 + * modify it under the terms of the GNU General Public License as
161.13 + * published by the Free Software Foundation; either version 2 of
161.14 + * the License, or (at your option) any later version.
161.15 + *
161.16 + * This program is distributed in the hope that it will be useful,
161.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
161.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161.19 + * GNU General Public License for more details.
161.20 + *
161.21 + * You should have received a copy of the GNU General Public License
161.22 + * along with this program; if not, write to the Free Software
161.23 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
161.24 + * Boston, MA 02110-1301, USA
161.25 + */
161.26 +
161.27 +#include <l4/devices/hw_mmio_register_block.h>
161.28 +#include "cpm-jz4780.h"
161.29 +
161.30 +
161.31 +
161.32 +enum Regs : unsigned
161.33 +{
161.34 + Clock_control = 0x000, // CPCCR
161.35 + Low_power_control = 0x004, // LCR
161.36 + Pll_control = 0x00c, // CPPCR
161.37 + Pll_control_A = 0x010, // CPAPCR
161.38 + Pll_control_M = 0x014, // CPMPCR
161.39 + Pll_control_E = 0x018, // CPEPCR
161.40 + Pll_control_V = 0x01c, // CPVPCR
161.41 + Clock_gate0 = 0x020, // CLKGR0
161.42 + Clock_gate1 = 0x028, // CLKGR1
161.43 + Sleep_control = 0x024, // OPCR (oscillator and power control)
161.44 + Ddr_divider = 0x02c, // DDRCDR
161.45 + I2s_divider0 = 0x060, // I2SCDR
161.46 + I2s_divider1 = 0x0a0, // I2S1CDR
161.47 + Lcd_divider0 = 0x054, // LP0CDR
161.48 + Lcd_divider1 = 0x064, // LP1CDR
161.49 + Msc_divider0 = 0x068, // MSC0CDR
161.50 + Msc_divider1 = 0x0a4, // MSC1CDR
161.51 + Msc_divider2 = 0x0a8, // MSC2CDR
161.52 + Uhc_divider = 0x06c, // UHCCDR
161.53 + Ssi_divider = 0x074, // SSICDR
161.54 +};
161.55 +
161.56 +enum Clock_bits : unsigned
161.57 +{
161.58 + Clock_enable = 22, // CE_CPU
161.59 + Clock_pclock_divider = 16, // PDIV (slow APB peripherals)
161.60 + Clock_hclock2_divider = 12, // H2DIV (fast AHB peripherals)
161.61 + Clock_hclock0_divider = 8, // H0DIV (fast AHB peripherals)
161.62 + Clock_cpu_divider = 0, // CDIV
161.63 +};
161.64 +
161.65 +enum Pll_bits : unsigned
161.66 +{
161.67 + Pll_multiplier = 19, // xPLLM
161.68 + Pll_input_division = 13, // xPLLN
161.69 + Pll_output_division = 9, // xPLLOD
161.70 + Pll_stable = 4, // xPLL_ON
161.71 + Pll_bypassed = 1, // xPLLBP
161.72 + Pll_enabled = 0, // xPLLEN
161.73 +};
161.74 +
161.75 +enum Clock_source_bits : unsigned
161.76 +{
161.77 + Clock_source_main = 30, // SEL_SRC (output to SCLK_A)
161.78 + Clock_source_cpu = 28, // SEL_CPLL (output to CCLK)
161.79 + Clock_source_hclock0 = 26, // SEL_H0PLL (output to AHB0)
161.80 + Clock_source_hclock2 = 24, // SEL_H2PLL (output to AHB2)
161.81 + Clock_source_ddr = 30, // DCS
161.82 + Clock_source_i2s = 31, // I2CS
161.83 + Clock_source_lcd = 30, // LPCS
161.84 +};
161.85 +
161.86 +enum Clock_sources : unsigned
161.87 +{
161.88 + Source_pll_A = 1, // APLL
161.89 + Source_external = 2, // EXCLK
161.90 + Source_realtime = 3, // RTCLK
161.91 + Source_main_frequency = 1, // SCLK_A
161.92 + Source_pll_M = 2, // MPLL
161.93 + Source_pll_E = 3, // EPLL
161.94 + Source_pll_V = 3, // VPLL
161.95 +};
161.96 +
161.97 +enum Clock_gate_bits : unsigned
161.98 +{
161.99 + Clock_gate_lcd = 28, // LCD (in CLKGR0)
161.100 + Clock_gate_tve = 27, // TVE (in CLKGR0)
161.101 + Clock_gate_smb4 = 12, // SMB4 (in CLKGR1)
161.102 + Clock_gate_smb3 = 0, // SMB3 (in CLKGR1)
161.103 + Clock_gate_smb2 = 25, // SMB2 (in CLKGR0)
161.104 + Clock_gate_smb1 = 6, // SMB2 (in CLKGR0)
161.105 + Clock_gate_smb0 = 5, // SMB2 (in CLKGR0)
161.106 +};
161.107 +
161.108 +enum Clock_gate_regs : unsigned
161.109 +{
161.110 + Clock_gate_reg_smb4 = Clock_gate1,
161.111 + Clock_gate_reg_smb3 = Clock_gate1,
161.112 + Clock_gate_reg_smb2 = Clock_gate0,
161.113 + Clock_gate_reg_smb1 = Clock_gate0,
161.114 + Clock_gate_reg_smb0 = Clock_gate0,
161.115 +};
161.116 +
161.117 +enum Divider_bits : unsigned
161.118 +{
161.119 + Ddr_divider_value = 0, // DDRCDR
161.120 + Lcd_divider_value = 0, // LPCDR
161.121 +};
161.122 +
161.123 +enum Lcd_clock_bits : unsigned
161.124 +{
161.125 + Lcd_change_enable = 0x1000, // CE_LCD
161.126 + Lcd_change_busy = 0x0800, // LCD_BUSY
161.127 + Lcd_clock_stop = 0x0400, // LCD_STOP
161.128 +};
161.129 +
161.130 +
161.131 +
161.132 +// If implemented as a Hw::Device, various properties would be
161.133 +// initialised in the constructor and obtained from the device tree
161.134 +// definitions.
161.135 +
161.136 +Cpm_jz4780_chip::Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq)
161.137 +: _exclk_freq(exclk_freq), _rtclk_freq(rtclk_freq)
161.138 +{
161.139 + _regs = new Hw::Mmio_register_block<32>(addr);
161.140 +
161.141 + // add_cid("cpm");
161.142 + // add_cid("cpm-jz4780");
161.143 + // register_property("exclk_freq", &_exclk_freq);
161.144 +}
161.145 +
161.146 +// Clock/timer control.
161.147 +// NOTE: For the time being, assume that the system is configured.
161.148 +
161.149 +int
161.150 +Cpm_jz4780_chip::have_clock()
161.151 +{
161.152 + // return !(_regs[Clock_gate] & (1 << Clock_gate_timer));
161.153 + return 1;
161.154 +}
161.155 +
161.156 +void
161.157 +Cpm_jz4780_chip::start_clock()
161.158 +{
161.159 + // _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer);
161.160 +}
161.161 +
161.162 +
161.163 +
161.164 +// Utility methods.
161.165 +
161.166 +uint32_t
161.167 +Cpm_jz4780_chip::get_field(uint32_t reg, uint32_t mask, uint8_t shift)
161.168 +{
161.169 + return (_regs[reg] & (mask << shift)) >> shift;
161.170 +}
161.171 +
161.172 +void
161.173 +Cpm_jz4780_chip::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value)
161.174 +{
161.175 + _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift);
161.176 +}
161.177 +
161.178 +// General clock divider access.
161.179 +
161.180 +uint8_t
161.181 +Cpm_jz4780_chip::_get_divider(uint32_t reg, uint32_t mask, uint8_t shift)
161.182 +{
161.183 + uint8_t d = get_field(reg, mask, shift);
161.184 +
161.185 + // NOTE: Value 14 stops the clock, 15 presumably resumes the clock.
161.186 +
161.187 + return (d < 14) ? d + 1 : 1;
161.188 +}
161.189 +
161.190 +
161.191 +
161.192 +// PLL control.
161.193 +
161.194 +// Return whether the PLL is stable.
161.195 +
161.196 +int
161.197 +Cpm_jz4780_chip::have_pll(uint32_t pll_reg)
161.198 +{
161.199 + return _regs[pll_reg] & (1 << Pll_stable);
161.200 +}
161.201 +
161.202 +int
161.203 +Cpm_jz4780_chip::pll_enabled(uint32_t pll_reg)
161.204 +{
161.205 + return _regs[pll_reg] & (1 << Pll_enabled);
161.206 +}
161.207 +
161.208 +int
161.209 +Cpm_jz4780_chip::pll_bypassed(uint32_t pll_reg)
161.210 +{
161.211 + return _regs[pll_reg] & (1 << Pll_bypassed);
161.212 +}
161.213 +
161.214 +// Feedback (13-bit) multiplier.
161.215 +
161.216 +uint16_t
161.217 +Cpm_jz4780_chip::get_multiplier(uint32_t pll_reg)
161.218 +{
161.219 + return get_field(pll_reg, 0x1fff, Pll_multiplier) + 1;
161.220 +}
161.221 +
161.222 +void
161.223 +Cpm_jz4780_chip::set_multiplier(uint32_t pll_reg, uint16_t multiplier)
161.224 +{
161.225 + set_field(pll_reg, 0x1fff, Pll_multiplier, multiplier - 1);
161.226 +}
161.227 +
161.228 +// Input (6-bit) divider.
161.229 +
161.230 +uint8_t
161.231 +Cpm_jz4780_chip::get_input_division(uint32_t pll_reg)
161.232 +{
161.233 + return get_field(pll_reg, 0x3f, Pll_input_division) + 1;
161.234 +}
161.235 +
161.236 +void
161.237 +Cpm_jz4780_chip::set_input_division(uint32_t pll_reg, uint8_t divider)
161.238 +{
161.239 + set_field(pll_reg, 0x3f, Pll_input_division, divider - 1);
161.240 +}
161.241 +
161.242 +// Output divider.
161.243 +
161.244 +uint8_t
161.245 +Cpm_jz4780_chip::get_output_division(uint32_t pll_reg)
161.246 +{
161.247 + uint8_t d = get_field(pll_reg, 0x0f, Pll_output_division);
161.248 +
161.249 + // Zero yields a division of one. Otherwise enforce even results.
161.250 +
161.251 + return d == 0 ? 1 : (d + 1) & 0x0e;
161.252 +}
161.253 +
161.254 +void
161.255 +Cpm_jz4780_chip::set_output_division(uint32_t pll_reg, uint8_t divider)
161.256 +{
161.257 + uint8_t d = divider <= 1 ? 0 : (divider & 0x0e) - 1;
161.258 +
161.259 + set_field(pll_reg, 0x0f, Pll_output_division, d);
161.260 +}
161.261 +
161.262 +uint32_t
161.263 +Cpm_jz4780_chip::get_pll_frequency(uint32_t pll_reg)
161.264 +{
161.265 + // Test for PLL enable and not PLL bypass.
161.266 +
161.267 + if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg))
161.268 + return (_exclk_freq * get_multiplier(pll_reg)) /
161.269 + (get_input_division(pll_reg) * get_output_division(pll_reg));
161.270 + else
161.271 + return _exclk_freq;
161.272 +}
161.273 +
161.274 +void
161.275 +Cpm_jz4780_chip::set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
161.276 +{
161.277 + set_multiplier(pll_reg, multiplier);
161.278 + set_input_division(pll_reg, in_divider);
161.279 + set_output_division(pll_reg, out_divider);
161.280 +
161.281 + if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg))
161.282 + while (!have_pll(pll_reg));
161.283 +}
161.284 +
161.285 +
161.286 +
161.287 +// CPU clock (CCLK) divider.
161.288 +
161.289 +uint8_t
161.290 +Cpm_jz4780_chip::get_cpu_divider()
161.291 +{
161.292 + return _get_divider(Clock_control, 0xf, Clock_cpu_divider);
161.293 +}
161.294 +
161.295 +// Fast peripheral clock (H0CLK) divider.
161.296 +
161.297 +uint8_t
161.298 +Cpm_jz4780_chip::get_hclock0_divider()
161.299 +{
161.300 + return _get_divider(Clock_control, 0xf, Clock_hclock0_divider);
161.301 +}
161.302 +
161.303 +// Fast peripheral clock (H2CLK) divider.
161.304 +
161.305 +uint8_t
161.306 +Cpm_jz4780_chip::get_hclock2_divider()
161.307 +{
161.308 + return _get_divider(Clock_control, 0xf, Clock_hclock2_divider);
161.309 +}
161.310 +
161.311 +// Slow peripheral clock (PCLK) divider.
161.312 +
161.313 +uint8_t
161.314 +Cpm_jz4780_chip::get_pclock_divider()
161.315 +{
161.316 + return _get_divider(Clock_control, 0xf, Clock_pclock_divider);
161.317 +}
161.318 +
161.319 +// LCD clock (LPCLK) divider for LCD0 pixel clock.
161.320 +
161.321 +uint8_t
161.322 +Cpm_jz4780_chip::get_lcd_pixel_divider()
161.323 +{
161.324 + return get_field(Lcd_divider0, 0xff, Lcd_divider_value) + 1;
161.325 +}
161.326 +
161.327 +// Memory clock (DDR_CLK) divider.
161.328 +
161.329 +uint8_t
161.330 +Cpm_jz4780_chip::get_memory_divider()
161.331 +{
161.332 + return _get_divider(Ddr_divider, 0xf, Ddr_divider_value);
161.333 +}
161.334 +
161.335 +// LCD pixel clock divider.
161.336 +// NOTE: This only supports the first LCD peripheral.
161.337 +
161.338 +void
161.339 +Cpm_jz4780_chip::set_lcd_pixel_divider(uint16_t division)
161.340 +{
161.341 + if ((division < 1) || (division > 256))
161.342 + return;
161.343 +
161.344 + // Enable change.
161.345 +
161.346 + _regs[Lcd_divider0] = _regs[Lcd_divider0] | Lcd_change_enable;
161.347 +
161.348 + // Set the divider.
161.349 +
161.350 + set_field(Lcd_divider0, 0xff, Lcd_divider_value, division - 1);
161.351 +
161.352 + // Restart clock and disable change.
161.353 +
161.354 + while (_regs[Lcd_divider0] & Lcd_change_busy);
161.355 + _regs[Lcd_divider0] = _regs[Lcd_divider0] & ~Lcd_change_enable;
161.356 +}
161.357 +
161.358 +
161.359 +
161.360 +// Clock gating control.
161.361 +
161.362 +void
161.363 +Cpm_jz4780_chip::start_lcd()
161.364 +{
161.365 + _regs[Clock_gate0] = _regs[Clock_gate0] & ~(1 << Clock_gate_lcd);
161.366 +}
161.367 +
161.368 +void
161.369 +Cpm_jz4780_chip::stop_lcd()
161.370 +{
161.371 + _regs[Clock_gate0] = _regs[Clock_gate0] | (1 << Clock_gate_lcd);
161.372 +}
161.373 +
161.374 +void
161.375 +Cpm_jz4780_chip::_update_i2c(uint8_t channel, int enable)
161.376 +{
161.377 + uint8_t bit;
161.378 + uint32_t reg;
161.379 + switch (channel)
161.380 + {
161.381 + case 0: bit = Clock_gate_smb0; reg = Clock_gate_reg_smb0; break;
161.382 + case 1: bit = Clock_gate_smb1; reg = Clock_gate_reg_smb1; break;
161.383 + case 2: bit = Clock_gate_smb2; reg = Clock_gate_reg_smb2; break;
161.384 + case 3: bit = Clock_gate_smb3; reg = Clock_gate_reg_smb3; break;
161.385 + case 4: bit = Clock_gate_smb4; reg = Clock_gate_reg_smb4; break;
161.386 + default: return;
161.387 + }
161.388 + if (enable)
161.389 + _regs[reg] = _regs[reg] & ~(1 << bit);
161.390 + else
161.391 + _regs[reg] = _regs[reg] | (1 << bit);
161.392 +}
161.393 +
161.394 +void
161.395 +Cpm_jz4780_chip::start_i2c(uint8_t channel)
161.396 +{
161.397 + _update_i2c(channel, 1);
161.398 +}
161.399 +
161.400 +void
161.401 +Cpm_jz4780_chip::stop_i2c(uint8_t channel)
161.402 +{
161.403 + _update_i2c(channel, 0);
161.404 +}
161.405 +
161.406 +
161.407 +
161.408 +// Clock sources.
161.409 +
161.410 +uint8_t
161.411 +Cpm_jz4780_chip::get_memory_source()
161.412 +{
161.413 + return get_field(Ddr_divider, 0x3, Clock_source_ddr);
161.414 +}
161.415 +
161.416 +uint32_t
161.417 +Cpm_jz4780_chip::get_memory_source_frequency()
161.418 +{
161.419 + switch (get_memory_source())
161.420 + {
161.421 + case Source_main_frequency:
161.422 + return get_main_frequency();
161.423 + case Source_pll_M:
161.424 + return get_pll_frequency(Pll_control_M);
161.425 + default:
161.426 + return 0;
161.427 + }
161.428 +}
161.429 +
161.430 +uint8_t
161.431 +Cpm_jz4780_chip::get_cpu_source()
161.432 +{
161.433 + return get_field(Clock_control, 0x3, Clock_source_cpu);
161.434 +}
161.435 +
161.436 +uint32_t
161.437 +Cpm_jz4780_chip::get_cpu_source_frequency()
161.438 +{
161.439 + switch (get_cpu_source())
161.440 + {
161.441 + case Source_main_frequency:
161.442 + return get_main_frequency();
161.443 + case Source_pll_M:
161.444 + return get_pll_frequency(Pll_control_M);
161.445 + case Source_pll_E:
161.446 + return get_pll_frequency(Pll_control_E);
161.447 + default:
161.448 + return 0;
161.449 + }
161.450 +}
161.451 +
161.452 +uint8_t
161.453 +Cpm_jz4780_chip::get_hclock0_source()
161.454 +{
161.455 + return get_field(Clock_control, 0x3, Clock_source_hclock0);
161.456 +}
161.457 +
161.458 +uint32_t
161.459 +Cpm_jz4780_chip::get_hclock0_source_frequency()
161.460 +{
161.461 + switch (get_hclock0_source())
161.462 + {
161.463 + case Source_main_frequency:
161.464 + return get_main_frequency();
161.465 + case Source_pll_M:
161.466 + return get_pll_frequency(Pll_control_M);
161.467 + case Source_pll_E:
161.468 + return get_pll_frequency(Pll_control_E);
161.469 + default:
161.470 + return 0;
161.471 + }
161.472 +}
161.473 +
161.474 +uint8_t
161.475 +Cpm_jz4780_chip::get_hclock2_source()
161.476 +{
161.477 + return get_field(Clock_control, 0x3, Clock_source_hclock2);
161.478 +}
161.479 +
161.480 +uint32_t
161.481 +Cpm_jz4780_chip::get_hclock2_source_frequency()
161.482 +{
161.483 + switch (get_hclock2_source())
161.484 + {
161.485 + case Source_main_frequency:
161.486 + return get_main_frequency();
161.487 + case Source_pll_M:
161.488 + return get_pll_frequency(Pll_control_M);
161.489 + case Source_realtime:
161.490 + return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code
161.491 + default:
161.492 + return 0;
161.493 + }
161.494 +}
161.495 +
161.496 +void
161.497 +Cpm_jz4780_chip::set_hclock2_source(uint8_t source)
161.498 +{
161.499 + set_field(Clock_control, 0x3, Clock_source_hclock2, source);
161.500 +}
161.501 +
161.502 +uint8_t
161.503 +Cpm_jz4780_chip::get_lcd_source()
161.504 +{
161.505 + return get_field(Lcd_divider0, 0x3, Clock_source_lcd);
161.506 +}
161.507 +
161.508 +uint32_t
161.509 +Cpm_jz4780_chip::get_lcd_source_frequency()
161.510 +{
161.511 + switch (get_lcd_source())
161.512 + {
161.513 + case Source_main_frequency:
161.514 + return get_main_frequency();
161.515 + case Source_pll_M:
161.516 + return get_pll_frequency(Pll_control_M);
161.517 + case Source_pll_V:
161.518 + return get_pll_frequency(Pll_control_V);
161.519 + default:
161.520 + return 0;
161.521 + }
161.522 +}
161.523 +
161.524 +void
161.525 +Cpm_jz4780_chip::set_lcd_source(uint8_t source)
161.526 +{
161.527 + // Stop clock and enable change.
161.528 +
161.529 + _regs[Lcd_divider0] = _regs[Lcd_divider0] | Lcd_change_enable | Lcd_clock_stop;
161.530 +
161.531 + // Set the source.
161.532 +
161.533 + set_field(Lcd_divider0, 0x03, Clock_source_lcd, source);
161.534 +
161.535 + // Restart clock and disable change.
161.536 +
161.537 + while (_regs[Lcd_divider0] & Lcd_change_busy);
161.538 + _regs[Lcd_divider0] = _regs[Lcd_divider0] & ~(Lcd_change_enable | Lcd_clock_stop);
161.539 +}
161.540 +
161.541 +uint8_t
161.542 +Cpm_jz4780_chip::get_pclock_source()
161.543 +{
161.544 + return get_hclock2_source();
161.545 +}
161.546 +
161.547 +uint32_t
161.548 +Cpm_jz4780_chip::get_pclock_source_frequency()
161.549 +{
161.550 + return get_hclock2_source_frequency();
161.551 +}
161.552 +
161.553 +void
161.554 +Cpm_jz4780_chip::set_pclock_source(uint8_t source)
161.555 +{
161.556 + set_hclock2_source(source);
161.557 +}
161.558 +
161.559 +
161.560 +
161.561 +// Source frequency, used by various clock sources.
161.562 +
161.563 +uint8_t
161.564 +Cpm_jz4780_chip::get_main_source()
161.565 +{
161.566 + return get_field(Clock_control, 0x3, Clock_source_main);
161.567 +}
161.568 +
161.569 +uint32_t
161.570 +Cpm_jz4780_chip::get_main_frequency()
161.571 +{
161.572 + switch (get_main_source())
161.573 + {
161.574 + case Source_pll_A:
161.575 + return get_pll_frequency(Pll_control_A);
161.576 + case Source_external:
161.577 + return _exclk_freq;
161.578 + case Source_realtime:
161.579 + return _rtclk_freq;
161.580 + default:
161.581 + return 0;
161.582 + }
161.583 +}
161.584 +
161.585 +// Clock frequency for the CPU.
161.586 +
161.587 +uint32_t
161.588 +Cpm_jz4780_chip::get_cpu_frequency()
161.589 +{
161.590 + return get_cpu_source_frequency() / get_cpu_divider();
161.591 +}
161.592 +
161.593 +// Clock frequency for fast peripherals.
161.594 +
161.595 +uint32_t
161.596 +Cpm_jz4780_chip::get_hclock0_frequency()
161.597 +{
161.598 + return get_hclock0_source_frequency() / get_hclock0_divider();
161.599 +}
161.600 +
161.601 +// Clock frequency for fast peripherals.
161.602 +
161.603 +uint32_t
161.604 +Cpm_jz4780_chip::get_hclock2_frequency()
161.605 +{
161.606 + return get_hclock2_source_frequency() / get_hclock2_divider();
161.607 +}
161.608 +
161.609 +// Clock frequency for slow peripherals.
161.610 +
161.611 +uint32_t
161.612 +Cpm_jz4780_chip::get_pclock_frequency()
161.613 +{
161.614 + return get_pclock_source_frequency() / get_pclock_divider();
161.615 +}
161.616 +
161.617 +// Clock frequency for the LCD0 controller.
161.618 +
161.619 +uint32_t
161.620 +Cpm_jz4780_chip::get_lcd_pixel_frequency()
161.621 +{
161.622 + return get_lcd_source_frequency() / get_lcd_pixel_divider();
161.623 +}
161.624 +
161.625 +// Clock frequency for the memory.
161.626 +
161.627 +uint32_t
161.628 +Cpm_jz4780_chip::get_memory_frequency()
161.629 +{
161.630 + return get_memory_source_frequency() / get_memory_divider();
161.631 +}
161.632 +
161.633 +uint32_t
161.634 +Cpm_jz4780_chip::get_apll_frequency()
161.635 +{
161.636 + return get_pll_frequency(Pll_control_A);
161.637 +}
161.638 +
161.639 +uint32_t
161.640 +Cpm_jz4780_chip::get_epll_frequency()
161.641 +{
161.642 + return get_pll_frequency(Pll_control_E);
161.643 +}
161.644 +
161.645 +uint32_t
161.646 +Cpm_jz4780_chip::get_mpll_frequency()
161.647 +{
161.648 + return get_pll_frequency(Pll_control_M);
161.649 +}
161.650 +
161.651 +uint32_t
161.652 +Cpm_jz4780_chip::get_vpll_frequency()
161.653 +{
161.654 + return get_pll_frequency(Pll_control_V);
161.655 +}
161.656 +
161.657 +
161.658 +
161.659 +// Set the pixel frequency.
161.660 +// Unlike the jz4740, HCLK/AHB0 is used as the device frequency, with the pixel
161.661 +// frequency being based on the selected clock source (SCLK_A, MPLL or VPLL).
161.662 +
161.663 +void
161.664 +Cpm_jz4780_chip::set_lcd_pixel_frequency(uint32_t pclk)
161.665 +{
161.666 + // Switch to the video PLL and attempt to set the divider.
161.667 +
161.668 + set_lcd_source(Source_pll_V);
161.669 + set_lcd_pixel_divider(get_lcd_source_frequency() / pclk);
161.670 +}
161.671 +
161.672 +// NOTE: Compatibility method. Probably needs reviewing.
161.673 +
161.674 +void
161.675 +Cpm_jz4780_chip::set_lcd_frequencies(uint32_t pclk, uint8_t ratio)
161.676 +{
161.677 + (void) ratio;
161.678 + set_lcd_pixel_frequency(pclk);
161.679 +}
161.680 +
161.681 +// NOTE: Empty method for compatibility.
161.682 +
161.683 +void
161.684 +Cpm_jz4780_chip::update_output_frequency()
161.685 +{
161.686 +}
161.687 +
161.688 +
161.689 +
161.690 +// C language interface functions.
161.691 +
161.692 +void
161.693 +*jz4780_cpm_init(l4_addr_t cpm_base)
161.694 +{
161.695 + /* Initialise the clock and power management peripheral with the
161.696 + register memory region and a 48MHz EXCLK frequency. */
161.697 +
161.698 + return (void *) new Cpm_jz4780_chip(cpm_base, 48000000, 32768);
161.699 +}
161.700 +
161.701 +int
161.702 +jz4780_cpm_have_clock(void *cpm)
161.703 +{
161.704 + return static_cast<Cpm_jz4780_chip *>(cpm)->have_clock();
161.705 +}
161.706 +
161.707 +void
161.708 +jz4780_cpm_start_clock(void *cpm)
161.709 +{
161.710 + static_cast<Cpm_jz4780_chip *>(cpm)->start_clock();
161.711 +}
161.712 +
161.713 +
161.714 +
161.715 +void
161.716 +jz4780_cpm_start_lcd(void *cpm)
161.717 +{
161.718 + static_cast<Cpm_jz4780_chip *>(cpm)->start_lcd();
161.719 +}
161.720 +
161.721 +void
161.722 +jz4780_cpm_stop_lcd(void *cpm)
161.723 +{
161.724 + static_cast<Cpm_jz4780_chip *>(cpm)->stop_lcd();
161.725 +}
161.726 +
161.727 +
161.728 +
161.729 +uint8_t
161.730 +jz4780_cpm_get_cpu_divider(void *cpm)
161.731 +{
161.732 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_cpu_divider();
161.733 +}
161.734 +
161.735 +uint8_t
161.736 +jz4780_cpm_get_hclock0_divider(void *cpm)
161.737 +{
161.738 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_divider();
161.739 +}
161.740 +
161.741 +uint8_t
161.742 +jz4780_cpm_get_hclock2_divider(void *cpm)
161.743 +{
161.744 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_divider();
161.745 +}
161.746 +
161.747 +uint8_t
161.748 +jz4780_cpm_get_lcd_pixel_divider(void *cpm)
161.749 +{
161.750 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_pixel_divider();
161.751 +}
161.752 +
161.753 +uint8_t
161.754 +jz4780_cpm_get_memory_divider(void *cpm)
161.755 +{
161.756 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_divider();
161.757 +}
161.758 +
161.759 +uint8_t
161.760 +jz4780_cpm_get_pclock_divider(void *cpm)
161.761 +{
161.762 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_divider();
161.763 +}
161.764 +
161.765 +
161.766 +
161.767 +uint8_t
161.768 +jz4780_cpm_get_hclock0_source(void *cpm)
161.769 +{
161.770 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_source();
161.771 +}
161.772 +
161.773 +uint8_t
161.774 +jz4780_cpm_get_hclock2_source(void *cpm)
161.775 +{
161.776 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_source();
161.777 +}
161.778 +
161.779 +uint8_t
161.780 +jz4780_cpm_get_lcd_source(void *cpm)
161.781 +{
161.782 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_source();
161.783 +}
161.784 +
161.785 +uint8_t
161.786 +jz4780_cpm_get_memory_source(void *cpm)
161.787 +{
161.788 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_source();
161.789 +}
161.790 +
161.791 +uint8_t
161.792 +jz4780_cpm_get_pclock_source(void *cpm)
161.793 +{
161.794 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_source();
161.795 +}
161.796 +
161.797 +void
161.798 +jz4780_cpm_set_pclock_source(void *cpm, uint8_t source)
161.799 +{
161.800 + static_cast<Cpm_jz4780_chip *>(cpm)->set_pclock_source(source);
161.801 +}
161.802 +
161.803 +
161.804 +
161.805 +uint32_t
161.806 +jz4780_cpm_get_hclock0_source_frequency(void *cpm)
161.807 +{
161.808 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_source_frequency();
161.809 +}
161.810 +
161.811 +uint32_t
161.812 +jz4780_cpm_get_hclock2_source_frequency(void *cpm)
161.813 +{
161.814 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_source_frequency();
161.815 +}
161.816 +
161.817 +uint32_t
161.818 +jz4780_cpm_get_lcd_source_frequency(void *cpm)
161.819 +{
161.820 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_source_frequency();
161.821 +}
161.822 +
161.823 +uint32_t
161.824 +jz4780_cpm_get_memory_source_frequency(void *cpm)
161.825 +{
161.826 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_source_frequency();
161.827 +}
161.828 +
161.829 +uint32_t
161.830 +jz4780_cpm_get_pclock_source_frequency(void *cpm)
161.831 +{
161.832 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_source_frequency();
161.833 +}
161.834 +
161.835 +
161.836 +
161.837 +uint8_t
161.838 +jz4780_cpm_get_main_source(void *cpm)
161.839 +{
161.840 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_main_source();
161.841 +}
161.842 +
161.843 +uint32_t
161.844 +jz4780_cpm_get_main_frequency(void *cpm)
161.845 +{
161.846 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_main_frequency();
161.847 +}
161.848 +
161.849 +uint32_t
161.850 +jz4780_cpm_get_cpu_frequency(void *cpm)
161.851 +{
161.852 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_cpu_frequency();
161.853 +}
161.854 +
161.855 +uint32_t
161.856 +jz4780_cpm_get_hclock0_frequency(void *cpm)
161.857 +{
161.858 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock0_frequency();
161.859 +}
161.860 +
161.861 +uint32_t
161.862 +jz4780_cpm_get_hclock2_frequency(void *cpm)
161.863 +{
161.864 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_hclock2_frequency();
161.865 +}
161.866 +
161.867 +uint32_t
161.868 +jz4780_cpm_get_lcd_pixel_frequency(void *cpm)
161.869 +{
161.870 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_lcd_pixel_frequency();
161.871 +}
161.872 +
161.873 +uint32_t
161.874 +jz4780_cpm_get_memory_frequency(void *cpm)
161.875 +{
161.876 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_memory_frequency();
161.877 +}
161.878 +
161.879 +uint32_t
161.880 +jz4780_cpm_get_pclock_frequency(void *cpm)
161.881 +{
161.882 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_pclock_frequency();
161.883 +}
161.884 +
161.885 +uint32_t
161.886 +jz4780_cpm_get_apll_frequency(void *cpm)
161.887 +{
161.888 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_apll_frequency();
161.889 +}
161.890 +
161.891 +uint32_t
161.892 +jz4780_cpm_get_epll_frequency(void *cpm)
161.893 +{
161.894 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_epll_frequency();
161.895 +}
161.896 +
161.897 +uint32_t
161.898 +jz4780_cpm_get_mpll_frequency(void *cpm)
161.899 +{
161.900 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_mpll_frequency();
161.901 +}
161.902 +
161.903 +uint32_t
161.904 +jz4780_cpm_get_vpll_frequency(void *cpm)
161.905 +{
161.906 + return static_cast<Cpm_jz4780_chip *>(cpm)->get_vpll_frequency();
161.907 +}
161.908 +
161.909 +
161.910 +
161.911 +void
161.912 +jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk)
161.913 +{
161.914 + static_cast<Cpm_jz4780_chip *>(cpm)->set_lcd_pixel_frequency(pclk);
161.915 +}
161.916 +
161.917 +void
161.918 +jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider)
161.919 +{
161.920 + static_cast<Cpm_jz4780_chip *>(cpm)->set_pll_parameters(Pll_control_M, multiplier, in_divider, out_divider);
161.921 +}
162.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
162.2 +++ b/pkg/devices/lib/gpio/Makefile Sun May 13 01:34:16 2018 +0200
162.3 @@ -0,0 +1,8 @@
162.4 +PKGDIR ?= ../..
162.5 +L4DIR ?= $(PKGDIR)/../..
162.6 +
162.7 +TARGET := include src
162.8 +
162.9 +include $(L4DIR)/mk/subdir.mk
162.10 +
162.11 +src: include
163.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
163.2 +++ b/pkg/devices/lib/gpio/include/Makefile Sun May 13 01:34:16 2018 +0200
163.3 @@ -0,0 +1,4 @@
163.4 +PKGDIR = ../../..
163.5 +L4DIR ?= $(PKGDIR)/../..
163.6 +
163.7 +include $(L4DIR)/mk/include.mk
164.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
164.2 +++ b/pkg/devices/lib/gpio/include/gpio-jz4730.h Sun May 13 01:34:16 2018 +0200
164.3 @@ -0,0 +1,188 @@
164.4 +/*
164.5 + * GPIO driver for Ingenic JZ4730.
164.6 + * (See below for additional copyright and licensing notices.)
164.7 + *
164.8 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
164.9 + *
164.10 + * This program is free software; you can redistribute it and/or
164.11 + * modify it under the terms of the GNU General Public License as
164.12 + * published by the Free Software Foundation; either version 2 of
164.13 + * the License, or (at your option) any later version.
164.14 + *
164.15 + * This program is distributed in the hope that it will be useful,
164.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
164.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
164.18 + * GNU General Public License for more details.
164.19 + *
164.20 + * You should have received a copy of the GNU General Public License
164.21 + * along with this program; if not, write to the Free Software
164.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
164.23 + * Boston, MA 02110-1301, USA
164.24 + *
164.25 + *
164.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
164.27 + * omap.cc GPIO driver implementations.
164.28 + *
164.29 + * This file is part of TUD:OS and distributed under the terms of the
164.30 + * GNU General Public License 2.
164.31 + * Please see the COPYING-GPL-2 file for details.
164.32 + */
164.33 +
164.34 +#pragma once
164.35 +
164.36 +#include <l4/sys/err.h>
164.37 +#include <l4/sys/types.h>
164.38 +#include <stdint.h>
164.39 +#include "gpio.h"
164.40 +
164.41 +
164.42 +
164.43 +#ifdef __cplusplus
164.44 +
164.45 +#include <l4/devices/hw_mmio_register_block.h>
164.46 +
164.47 +// GPIO device control.
164.48 +
164.49 +class Gpio_jz4730_irq_pin : public Hw::Gpio_irq_pin
164.50 +{
164.51 + unsigned _pin;
164.52 + Hw::Register_block<32> _regs;
164.53 +
164.54 + // Convenience method for obtaining the bit corresponding to a pin.
164.55 +
164.56 + l4_uint32_t _pin_bit(unsigned pin)
164.57 + { return 1 << (pin & 31); }
164.58 +
164.59 + void write_reg_pin(unsigned reg);
164.60 +
164.61 + // Convenience methods for clearing and setting bits in the absence of
164.62 + // dedicated registers.
164.63 +
164.64 + void clear_reg_pin(unsigned reg);
164.65 + void set_reg_pin(unsigned reg);
164.66 + void clear_reg_pins(uint32_t reg_upper, uint32_t reg_lower);
164.67 + void set_reg_pins(uint32_t reg_upper, uint32_t reg_lower, uint8_t value);
164.68 +
164.69 +public:
164.70 + Gpio_jz4730_irq_pin(unsigned pin, Hw::Register_block<32> const ®s);
164.71 +
164.72 + void do_mask();
164.73 + void do_unmask();
164.74 + bool do_set_mode(unsigned mode);
164.75 + int clear();
164.76 + bool enabled();
164.77 +};
164.78 +
164.79 +class Gpio_jz4730_chip : public Hw::Gpio_chip
164.80 +{
164.81 +private:
164.82 + Hw::Register_block<32> _regs;
164.83 +
164.84 + l4_addr_t _start, _end;
164.85 + unsigned _nr_pins;
164.86 +
164.87 + // Convenience method for obtaining the bit corresponding to a pin.
164.88 +
164.89 + l4_uint32_t _pin_bit(unsigned pin)
164.90 + { return 1 << (pin & 31); }
164.91 +
164.92 + // Convenience method for obtaining the bit position of a pin.
164.93 +
164.94 + unsigned _pin_shift(unsigned pin)
164.95 + { return pin % 32; }
164.96 +
164.97 + // Permit only "aligned" accesses to registers.
164.98 +
164.99 + unsigned _reg_offset_check(unsigned pin_offset) const
164.100 + {
164.101 + switch (pin_offset)
164.102 + {
164.103 + case 0:
164.104 + return 0;
164.105 +
164.106 + default:
164.107 + throw -L4_EINVAL;
164.108 + }
164.109 + }
164.110 +
164.111 + // General configuration register updates.
164.112 +
164.113 + void _config(unsigned bitmap, unsigned mode);
164.114 +
164.115 + // General pull-up register updates.
164.116 +
164.117 + void _config_pull(unsigned bitmap, unsigned mode);
164.118 +
164.119 + // General pad register updates.
164.120 +
164.121 + void _config_pad(unsigned bitmap, unsigned func, unsigned value);
164.122 +
164.123 +public:
164.124 + Gpio_jz4730_chip(l4_addr_t start, l4_addr_t end,
164.125 + unsigned nr_pins);
164.126 +
164.127 + // Obtain the number of pins.
164.128 +
164.129 + unsigned nr_pins() const { return _nr_pins; }
164.130 +
164.131 + // Unnecessary operations.
164.132 +
164.133 + void request(unsigned) {}
164.134 + void free(unsigned) {}
164.135 +
164.136 + // Configuration methods.
164.137 +
164.138 + void setup(unsigned pin, unsigned mode, int value = 0);
164.139 + void config_pull(unsigned pin, unsigned mode);
164.140 + void config_pad(unsigned pin, unsigned func, unsigned value);
164.141 + void config_get(unsigned pin, unsigned reg, unsigned *value);
164.142 +
164.143 + // Multiple pin configuration methods.
164.144 +
164.145 + void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues = 0);
164.146 + void multi_config_pull(Pin_slice const &mask, unsigned mode);
164.147 + void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value = 0);
164.148 + void multi_set(Pin_slice const &mask, unsigned data);
164.149 + unsigned multi_get(unsigned offset);
164.150 +
164.151 + // IRQ pin configuration.
164.152 +
164.153 + Hw::Gpio_irq_pin *get_irq(unsigned pin);
164.154 +
164.155 + // Pin/port data methods.
164.156 +
164.157 + int get(unsigned pin);
164.158 + void set(unsigned pin, int value);
164.159 +
164.160 +private:
164.161 + void config(unsigned pin, unsigned mode);
164.162 +};
164.163 +
164.164 +#endif /* __cplusplus */
164.165 +
164.166 +
164.167 +
164.168 +/* C language interface. */
164.169 +
164.170 +EXTERN_C_BEGIN
164.171 +
164.172 +void *jz4730_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins);
164.173 +
164.174 +void jz4730_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value);
164.175 +void jz4730_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
164.176 +void jz4730_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value);
164.177 +void jz4730_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value);
164.178 +
164.179 +void jz4730_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues);
164.180 +void jz4730_gpio_multi_config_pull(void *gpio, Pin_slice const *mask, unsigned mode);
164.181 +void jz4730_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value);
164.182 +void jz4730_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data);
164.183 +unsigned jz4730_gpio_multi_get(void *gpio, unsigned offset);
164.184 +
164.185 +int jz4730_gpio_get(void *gpio, unsigned pin);
164.186 +void jz4730_gpio_set(void *gpio, unsigned pin, int value);
164.187 +
164.188 +void *jz4730_gpio_get_irq(void *gpio, unsigned pin);
164.189 +bool jz4730_gpio_irq_set_mode(void *gpio_irq, unsigned mode);
164.190 +
164.191 +EXTERN_C_END
165.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
165.2 +++ b/pkg/devices/lib/gpio/include/gpio-jz4740.h Sun May 13 01:34:16 2018 +0200
165.3 @@ -0,0 +1,180 @@
165.4 +/*
165.5 + * GPIO driver for Ingenic JZ4740.
165.6 + * (See below for additional copyright and licensing notices.)
165.7 + *
165.8 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
165.9 + *
165.10 + * This program is free software; you can redistribute it and/or
165.11 + * modify it under the terms of the GNU General Public License as
165.12 + * published by the Free Software Foundation; either version 2 of
165.13 + * the License, or (at your option) any later version.
165.14 + *
165.15 + * This program is distributed in the hope that it will be useful,
165.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
165.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165.18 + * GNU General Public License for more details.
165.19 + *
165.20 + * You should have received a copy of the GNU General Public License
165.21 + * along with this program; if not, write to the Free Software
165.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
165.23 + * Boston, MA 02110-1301, USA
165.24 + *
165.25 + *
165.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
165.27 + * omap.cc GPIO driver implementations.
165.28 + *
165.29 + * This file is part of TUD:OS and distributed under the terms of the
165.30 + * GNU General Public License 2.
165.31 + * Please see the COPYING-GPL-2 file for details.
165.32 + */
165.33 +
165.34 +#pragma once
165.35 +
165.36 +#include <l4/sys/err.h>
165.37 +#include <l4/sys/types.h>
165.38 +#include <stdint.h>
165.39 +#include "gpio.h"
165.40 +
165.41 +
165.42 +
165.43 +#ifdef __cplusplus
165.44 +
165.45 +#include <l4/devices/hw_mmio_register_block.h>
165.46 +
165.47 +// GPIO device control.
165.48 +
165.49 +class Gpio_jz4740_irq_pin : public Hw::Gpio_irq_pin
165.50 +{
165.51 + unsigned _pin;
165.52 + Hw::Register_block<32> _regs;
165.53 +
165.54 + // Convenience method for obtaining the bit corresponding to a pin.
165.55 +
165.56 + l4_uint32_t _pin_bit(unsigned pin)
165.57 + { return 1 << (pin & 31); }
165.58 +
165.59 + void write_reg_pin(unsigned reg);
165.60 +
165.61 +public:
165.62 + Gpio_jz4740_irq_pin(unsigned pin, Hw::Register_block<32> const ®s);
165.63 +
165.64 + void do_mask();
165.65 + void do_unmask();
165.66 + bool do_set_mode(unsigned mode);
165.67 + int clear();
165.68 + bool enabled();
165.69 +};
165.70 +
165.71 +class Gpio_jz4740_chip : public Hw::Gpio_chip
165.72 +{
165.73 +private:
165.74 + Hw::Register_block<32> _regs;
165.75 +
165.76 + l4_addr_t _start, _end;
165.77 + unsigned _nr_pins;
165.78 +
165.79 + // Convenience method for obtaining the bit corresponding to a pin.
165.80 +
165.81 + l4_uint32_t _pin_bit(unsigned pin)
165.82 + { return 1 << (pin & 31); }
165.83 +
165.84 + // Convenience method for obtaining the bit position of a pin.
165.85 +
165.86 + unsigned _pin_shift(unsigned pin)
165.87 + { return pin % 32; }
165.88 +
165.89 + // Permit only "aligned" accesses to registers.
165.90 +
165.91 + unsigned _reg_offset_check(unsigned pin_offset) const
165.92 + {
165.93 + switch (pin_offset)
165.94 + {
165.95 + case 0:
165.96 + return 0;
165.97 +
165.98 + default:
165.99 + throw -L4_EINVAL;
165.100 + }
165.101 + }
165.102 +
165.103 + // General configuration register updates.
165.104 +
165.105 + void _config(unsigned bitmap, unsigned mode);
165.106 +
165.107 + // General pull-up register updates.
165.108 +
165.109 + void _config_pull(unsigned bitmap, unsigned mode);
165.110 +
165.111 + // General pad register updates.
165.112 +
165.113 + void _config_pad(unsigned bitmap, unsigned func, unsigned value);
165.114 +
165.115 +public:
165.116 + Gpio_jz4740_chip(l4_addr_t start, l4_addr_t end,
165.117 + unsigned nr_pins);
165.118 +
165.119 + // Obtain the number of pins.
165.120 +
165.121 + unsigned nr_pins() const { return _nr_pins; }
165.122 +
165.123 + // Unnecessary operations.
165.124 +
165.125 + void request(unsigned) {}
165.126 + void free(unsigned) {}
165.127 +
165.128 + // Configuration methods.
165.129 +
165.130 + void setup(unsigned pin, unsigned mode, int value = 0);
165.131 + void config_pull(unsigned pin, unsigned mode);
165.132 + void config_pad(unsigned pin, unsigned func, unsigned value);
165.133 + void config_get(unsigned pin, unsigned reg, unsigned *value);
165.134 +
165.135 + // Multiple pin configuration methods.
165.136 +
165.137 + void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues = 0);
165.138 + void multi_config_pull(Pin_slice const &mask, unsigned mode);
165.139 + void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value = 0);
165.140 + void multi_set(Pin_slice const &mask, unsigned data);
165.141 + unsigned multi_get(unsigned offset);
165.142 +
165.143 + // IRQ pin configuration.
165.144 +
165.145 + Hw::Gpio_irq_pin *get_irq(unsigned pin);
165.146 +
165.147 + // Pin/port data methods.
165.148 +
165.149 + int get(unsigned pin);
165.150 + void set(unsigned pin, int value);
165.151 +
165.152 +private:
165.153 + void config(unsigned pin, unsigned mode);
165.154 +};
165.155 +
165.156 +#endif /* __cplusplus */
165.157 +
165.158 +
165.159 +
165.160 +/* C language interface. */
165.161 +
165.162 +EXTERN_C_BEGIN
165.163 +
165.164 +void *jz4740_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins);
165.165 +
165.166 +void jz4740_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value);
165.167 +void jz4740_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
165.168 +void jz4740_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value);
165.169 +void jz4740_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value);
165.170 +
165.171 +void jz4740_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues);
165.172 +void jz4740_gpio_multi_config_pull(void *gpio, Pin_slice const *mask, unsigned mode);
165.173 +void jz4740_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value);
165.174 +void jz4740_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data);
165.175 +unsigned jz4740_gpio_multi_get(void *gpio, unsigned offset);
165.176 +
165.177 +int jz4740_gpio_get(void *gpio, unsigned pin);
165.178 +void jz4740_gpio_set(void *gpio, unsigned pin, int value);
165.179 +
165.180 +void *jz4740_gpio_get_irq(void *gpio, unsigned pin);
165.181 +bool jz4740_gpio_irq_set_mode(void *gpio_irq, unsigned mode);
165.182 +
165.183 +EXTERN_C_END
166.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
166.2 +++ b/pkg/devices/lib/gpio/include/gpio-jz4780.h Sun May 13 01:34:16 2018 +0200
166.3 @@ -0,0 +1,169 @@
166.4 +/*
166.5 + * GPIO driver for Ingenic JZ4780.
166.6 + * (See below for additional copyright and licensing notices.)
166.7 + *
166.8 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
166.9 + *
166.10 + * This program is free software; you can redistribute it and/or
166.11 + * modify it under the terms of the GNU General Public License as
166.12 + * published by the Free Software Foundation; either version 2 of
166.13 + * the License, or (at your option) any later version.
166.14 + *
166.15 + * This program is distributed in the hope that it will be useful,
166.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
166.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
166.18 + * GNU General Public License for more details.
166.19 + *
166.20 + * You should have received a copy of the GNU General Public License
166.21 + * along with this program; if not, write to the Free Software
166.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
166.23 + * Boston, MA 02110-1301, USA
166.24 + *
166.25 + *
166.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
166.27 + * omap.cc GPIO driver implementations.
166.28 + *
166.29 + * This file is part of TUD:OS and distributed under the terms of the
166.30 + * GNU General Public License 2.
166.31 + * Please see the COPYING-GPL-2 file for details.
166.32 + */
166.33 +
166.34 +#pragma once
166.35 +
166.36 +#include <l4/sys/err.h>
166.37 +#include <l4/sys/types.h>
166.38 +#include <stdint.h>
166.39 +#include "gpio.h"
166.40 +
166.41 +
166.42 +
166.43 +#ifdef __cplusplus
166.44 +
166.45 +#include <l4/devices/hw_mmio_register_block.h>
166.46 +
166.47 +// GPIO device control.
166.48 +
166.49 +class Gpio_jz4780_irq_pin : public Hw::Gpio_irq_pin
166.50 +{
166.51 + unsigned _pin;
166.52 + Hw::Register_block<32> _regs;
166.53 +
166.54 + // Convenience method for obtaining the bit corresponding to a pin.
166.55 +
166.56 + l4_uint32_t _pin_bit(unsigned pin)
166.57 + { return 1 << (pin & 31); }
166.58 +
166.59 + void write_reg_pin(unsigned reg);
166.60 +
166.61 +public:
166.62 + Gpio_jz4780_irq_pin(unsigned pin, Hw::Register_block<32> const ®s);
166.63 +
166.64 + void do_mask();
166.65 + void do_unmask();
166.66 + bool do_set_mode(unsigned mode);
166.67 + int clear();
166.68 + bool enabled();
166.69 +};
166.70 +
166.71 +class Gpio_jz4780_chip : public Hw::Gpio_chip
166.72 +{
166.73 +private:
166.74 + Hw::Register_block<32> _regs;
166.75 +
166.76 + l4_addr_t _start, _end;
166.77 + unsigned _nr_pins;
166.78 + l4_uint32_t _pull_ups, _pull_downs;
166.79 +
166.80 + // Convenience method for obtaining the bit corresponding to a pin.
166.81 +
166.82 + l4_uint32_t _pin_bit(unsigned pin)
166.83 + { return 1 << (pin & 31); }
166.84 +
166.85 + // Convenience method for obtaining the bit position of a pin.
166.86 +
166.87 + unsigned _pin_shift(unsigned pin)
166.88 + { return pin % 32; }
166.89 +
166.90 + // Permit only "aligned" accesses to registers.
166.91 +
166.92 + unsigned _reg_offset_check(unsigned pin_offset) const
166.93 + {
166.94 + switch (pin_offset)
166.95 + {
166.96 + case 0:
166.97 + return 0;
166.98 +
166.99 + default:
166.100 + throw -L4_EINVAL;
166.101 + }
166.102 + }
166.103 +
166.104 +public:
166.105 + Gpio_jz4780_chip(l4_addr_t start, l4_addr_t end,
166.106 + unsigned nr_pins,
166.107 + l4_uint32_t pull_ups, l4_uint32_t pull_downs);
166.108 +
166.109 + // Obtain the number of pins.
166.110 +
166.111 + unsigned nr_pins() const { return _nr_pins; }
166.112 +
166.113 + // Unnecessary operations.
166.114 +
166.115 + void request(unsigned) {}
166.116 + void free(unsigned) {}
166.117 +
166.118 + // Configuration methods.
166.119 +
166.120 + void setup(unsigned pin, unsigned mode, int value = 0);
166.121 + void config_pull(unsigned pin, unsigned mode);
166.122 + void config_pad(unsigned pin, unsigned func, unsigned value);
166.123 + void config_get(unsigned pin, unsigned reg, unsigned *value);
166.124 +
166.125 + // Multiple pin configuration methods.
166.126 +
166.127 + void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues = 0);
166.128 + void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value = 0);
166.129 + void multi_set(Pin_slice const &mask, unsigned data);
166.130 + unsigned multi_get(unsigned offset);
166.131 +
166.132 + // IRQ pin configuration.
166.133 +
166.134 + Hw::Gpio_irq_pin *get_irq(unsigned pin);
166.135 +
166.136 + // Pin/port data methods.
166.137 +
166.138 + int get(unsigned pin);
166.139 + void set(unsigned pin, int value);
166.140 +
166.141 +private:
166.142 + void config(unsigned pin, unsigned mode);
166.143 +};
166.144 +
166.145 +#endif /* __cplusplus */
166.146 +
166.147 +
166.148 +
166.149 +/* C language interface. */
166.150 +
166.151 +EXTERN_C_BEGIN
166.152 +
166.153 +void *jz4780_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
166.154 + l4_uint32_t pull_ups, l4_uint32_t pull_downs);
166.155 +
166.156 +void jz4780_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value);
166.157 +void jz4780_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
166.158 +void jz4780_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value);
166.159 +void jz4780_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value);
166.160 +
166.161 +void jz4780_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues);
166.162 +void jz4780_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value);
166.163 +void jz4780_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data);
166.164 +unsigned jz4780_gpio_multi_get(void *gpio, unsigned offset);
166.165 +
166.166 +int jz4780_gpio_get(void *gpio, unsigned pin);
166.167 +void jz4780_gpio_set(void *gpio, unsigned pin, int value);
166.168 +
166.169 +void *jz4780_gpio_get_irq(void *gpio, unsigned pin);
166.170 +bool jz4780_gpio_irq_set_mode(void *gpio_irq, unsigned mode);
166.171 +
166.172 +EXTERN_C_END
167.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
167.2 +++ b/pkg/devices/lib/gpio/include/gpio.h Sun May 13 01:34:16 2018 +0200
167.3 @@ -0,0 +1,215 @@
167.4 +/*
167.5 + * GPIO driver definitions.
167.6 + * (See below for additional copyright and licensing notices.)
167.7 + *
167.8 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
167.9 + *
167.10 + * This program is free software; you can redistribute it and/or
167.11 + * modify it under the terms of the GNU General Public License as
167.12 + * published by the Free Software Foundation; either version 2 of
167.13 + * the License, or (at your option) any later version.
167.14 + *
167.15 + * This program is distributed in the hope that it will be useful,
167.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
167.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
167.18 + * GNU General Public License for more details.
167.19 + *
167.20 + * You should have received a copy of the GNU General Public License
167.21 + * along with this program; if not, write to the Free Software
167.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
167.23 + * Boston, MA 02110-1301, USA
167.24 + *
167.25 + *
167.26 + * Subject to other copyrights, being derived from the gpio headers in the io
167.27 + * package.
167.28 + *
167.29 + * This file is part of TUD:OS and distributed under the terms of the
167.30 + * GNU General Public License 2.
167.31 + * Please see the COPYING-GPL-2 file for details.
167.32 + */
167.33 +
167.34 +#pragma once
167.35 +
167.36 +#include <l4/vbus/vbus_gpio.h>
167.37 +
167.38 +typedef struct Pin_slice
167.39 +{
167.40 + unsigned offset;
167.41 + unsigned mask;
167.42 +} Pin_slice;
167.43 +
167.44 +#ifdef __cplusplus
167.45 +
167.46 +namespace Hw {
167.47 +
167.48 +// IRQ control for each GPIO pin.
167.49 +
167.50 +class Gpio_irq_pin
167.51 +{
167.52 +public:
167.53 + virtual void do_mask() = 0;
167.54 + virtual void do_unmask() = 0;
167.55 + virtual bool do_set_mode(unsigned mode) = 0;
167.56 + virtual int clear() = 0;
167.57 + virtual bool enabled() = 0;
167.58 +};
167.59 +
167.60 +// GPIO peripheral control.
167.61 +
167.62 +class Gpio_chip
167.63 +{
167.64 +public:
167.65 + /// Modes used for setup()
167.66 + enum Fix_mode
167.67 + {
167.68 + Input = L4VBUS_GPIO_SETUP_INPUT, ///< Configure as input pin
167.69 + Output = L4VBUS_GPIO_SETUP_OUTPUT, ///< Configure as output pin
167.70 + Irq = L4VBUS_GPIO_SETUP_IRQ, ///< Configure as IRQ source
167.71 + };
167.72 +
167.73 + /// Modes used for pull up / pull down (config_pull())
167.74 + enum Pull_mode
167.75 + {
167.76 + Pull_none = L4VBUS_GPIO_PIN_PULL_NONE, ///< No pull up or pull down resistors
167.77 + Pull_up = L4VBUS_GPIO_PIN_PULL_UP, ///< Enable pull up resistor
167.78 + Pull_down = L4VBUS_GPIO_PIN_PULL_DOWN, ///< Enable pull down resistor
167.79 + };
167.80 +
167.81 + // Generic function options
167.82 + enum Function_levels
167.83 + {
167.84 + Function_gpio,
167.85 + Function_alt,
167.86 + };
167.87 +
167.88 + virtual void request(unsigned pin) = 0;
167.89 + virtual void free(unsigned pin) = 0;
167.90 +
167.91 + /**
167.92 + * \brief Request number of pins from GPIO chip
167.93 + * \return Number of pins of this GPIO chip
167.94 + */
167.95 + virtual unsigned nr_pins() const = 0;
167.96 +
167.97 + /**
167.98 + * \brief Generic (platform independent) setup for a pin.
167.99 + * \param pin the pin number to configure.
167.100 + * \param mode the mode for the pin (see Fix_mode).
167.101 + * \param value the value if the pin is configured as output.
167.102 + */
167.103 + virtual void setup(unsigned pin, unsigned mode, int value = 0) = 0;
167.104 +
167.105 + /**
167.106 + * \brief Generic (platform independet) function to set a pin's pull up/down mode
167.107 + * \param pin The pin number to configure.
167.108 + * \param mode The pull up/down mode (see Pull_mode).
167.109 + */
167.110 + virtual void config_pull(unsigned pin, unsigned mode) = 0;
167.111 +
167.112 + /**
167.113 + * \brief Set platform specific pad configuration.
167.114 + * \param pin the pin to configure.
167.115 + * \param func a platform specific sub-function of a pad to be configured
167.116 + * \param value a platform specific value for the given sub-function.
167.117 + */
167.118 + virtual void config_pad(unsigned pin, unsigned func, unsigned value) = 0;
167.119 +
167.120 + /**
167.121 + * \brief Get Platform specific pad configuration.
167.122 + * \param pin the pin to configure.
167.123 + * \param func a platform specific sub-function of a pad to be configured
167.124 + * \retparam value a platform specific value for the given sub-function.
167.125 + */
167.126 + virtual void config_get(unsigned pin, unsigned func, unsigned *value) = 0;
167.127 +
167.128 + /**
167.129 + * \brief Get the value of the given pin (generic API).
167.130 + * \param pin the pin to read the value from.
167.131 + */
167.132 + virtual int get(unsigned pin) = 0;
167.133 +
167.134 + /**
167.135 + * \brief Set the value of the given pin (generic API).
167.136 + * \pre The pin has to be configured as output before using this function,
167.137 + * otherwise this call will be ignored.
167.138 + * \param pin the pin to write the value to.
167.139 + * \param value the value to program for output (0 or 1).
167.140 + */
167.141 + virtual void set(unsigned pin, int value) = 0;
167.142 +
167.143 + /**
167.144 + * \brief Setup multiple pins (generic API)
167.145 + * \param mask the pins to actually set up.
167.146 + * \param mode the mode for the pins (see Fix_mode).
167.147 + * \param outvalue the value if configured as output.
167.148 + */
167.149 + virtual void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalue = 0) = 0;
167.150 +
167.151 + /**
167.152 + * \brief Configure multiple pads at once (platform specific API).
167.153 + * \param mask the pads to configure.
167.154 + * \param func the platform-specific sub-function to configure.
167.155 + * \param value the platform-specific value to set for the sub-function.
167.156 + * \see config_pad()
167.157 + */
167.158 + virtual void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value) = 0;
167.159 +
167.160 + /**
167.161 + * \brief Set the value for multiple output pins at once.
167.162 + * \param mask the pins that shall actually be set to the given values.
167.163 + * \param data the bit-wise value for each pin to set (according to mask).
167.164 + */
167.165 + virtual void multi_set(Pin_slice const &mask, unsigned data) = 0;
167.166 +
167.167 + /**
167.168 + * \brief Get the value for all pins at once.
167.169 + */
167.170 + virtual unsigned multi_get(unsigned offset) = 0;
167.171 +
167.172 +
167.173 + void output(unsigned pin, int value)
167.174 + { setup(pin, Output, value); }
167.175 +
167.176 + void input(unsigned pin)
167.177 + { setup(pin, Input); }
167.178 +
167.179 + void multi_output(Pin_slice const &mask, unsigned data)
167.180 + { multi_setup(mask, mask.mask, data); }
167.181 +
167.182 + void multi_input(Pin_slice const &mask)
167.183 + { multi_setup(mask, ~mask.mask); }
167.184 +};
167.185 +
167.186 +}
167.187 +
167.188 +#else
167.189 +
167.190 +typedef enum {
167.191 + false = 0,
167.192 + true = 1
167.193 +} bool;
167.194 +
167.195 +/// Modes used for setup()
167.196 +enum Fix_mode
167.197 +{
167.198 + Fix_input = L4VBUS_GPIO_SETUP_INPUT, ///< Configure as input pin
167.199 + Fix_output = L4VBUS_GPIO_SETUP_OUTPUT, ///< Configure as output pin
167.200 + Fix_irq = L4VBUS_GPIO_SETUP_IRQ, ///< Configure as IRQ source
167.201 +};
167.202 +
167.203 +/// Modes used for pull up / pull down (config_pull())
167.204 +enum Pull_mode
167.205 +{
167.206 + Pull_none = L4VBUS_GPIO_PIN_PULL_NONE, ///< No pull up or pull down resistors
167.207 + Pull_up = L4VBUS_GPIO_PIN_PULL_UP, ///< Enable pull up resistor
167.208 + Pull_down = L4VBUS_GPIO_PIN_PULL_DOWN, ///< Enable pull down resistor
167.209 +};
167.210 +
167.211 +// Generic function options
167.212 +enum Function_levels
167.213 +{
167.214 + Function_gpio,
167.215 + Function_alt,
167.216 +};
167.217 +
167.218 +#endif /* __cplusplus */
168.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
168.2 +++ b/pkg/devices/lib/gpio/src/Makefile Sun May 13 01:34:16 2018 +0200
168.3 @@ -0,0 +1,13 @@
168.4 +PKGDIR ?= ../../..
168.5 +L4DIR ?= $(PKGDIR)/../..
168.6 +
168.7 +TARGET = libgpio.o.a
168.8 +PC_FILENAME := libdrivers-gpio
168.9 +
168.10 +SRC_CC := jz4730.cc jz4740.cc jz4780.cc
168.11 +
168.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/gpio/include
168.13 +
168.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common
168.15 +
168.16 +include $(L4DIR)/mk/lib.mk
169.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
169.2 +++ b/pkg/devices/lib/gpio/src/jz4730.cc Sun May 13 01:34:16 2018 +0200
169.3 @@ -0,0 +1,519 @@
169.4 +/*
169.5 + * GPIO driver for Ingenic JZ4730.
169.6 + * (See below for additional copyright and licensing notices.)
169.7 + *
169.8 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
169.9 + *
169.10 + * This program is free software; you can redistribute it and/or
169.11 + * modify it under the terms of the GNU General Public License as
169.12 + * published by the Free Software Foundation; either version 2 of
169.13 + * the License, or (at your option) any later version.
169.14 + *
169.15 + * This program is distributed in the hope that it will be useful,
169.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
169.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
169.18 + * GNU General Public License for more details.
169.19 + *
169.20 + * You should have received a copy of the GNU General Public License
169.21 + * along with this program; if not, write to the Free Software
169.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
169.23 + * Boston, MA 02110-1301, USA
169.24 + *
169.25 + *
169.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
169.27 + * omap.cc GPIO driver implementations.
169.28 + *
169.29 + * This file is part of TUD:OS and distributed under the terms of the
169.30 + * GNU General Public License 2.
169.31 + * Please see the COPYING-GPL-2 file for details.
169.32 + */
169.33 +
169.34 +#include <l4/sys/icu.h>
169.35 +#include <l4/util/util.h>
169.36 +#include <l4/devices/hw_mmio_register_block.h>
169.37 +
169.38 +#include "gpio-jz4730.h"
169.39 +
169.40 +// GPIO register offsets (x in A..D).
169.41 +
169.42 +enum Regs
169.43 +{
169.44 + Port_data = 0x000, // PxGPDR
169.45 + Port_direction = 0x004, // PxGPDIR
169.46 + Pull_enable = 0x00c, // PxGPPUR
169.47 + Port_function_lower = 0x010, // PxGPALR
169.48 + Port_function_upper = 0x014, // PxGPAUR
169.49 + Irq_detect_lower = 0x018, // PxGPDLR
169.50 + Irq_detect_upper = 0x01c, // PxGPDUR
169.51 + Irq_enable = 0x020, // PxGPIER
169.52 + Irq_flag = 0x028, // PxGPFR
169.53 +};
169.54 +
169.55 +
169.56 +
169.57 +// Select the appropriate register and pin where two bits are assigned per pin,
169.58 +// thus requiring two 32-bit registers to hold the configuration of 32 pins.
169.59 +
169.60 +static
169.61 +uint32_t
169.62 +_select_bank_for_pin(uint32_t reg_upper, uint32_t reg_lower, uint8_t pin, uint8_t *pin_out)
169.63 +{
169.64 + if (pin < 16)
169.65 + {
169.66 + *pin_out = pin;
169.67 + return reg_lower;
169.68 + }
169.69 + else
169.70 + {
169.71 + *pin_out = pin - 16;
169.72 + return reg_upper;
169.73 + }
169.74 +}
169.75 +
169.76 +
169.77 +
169.78 +// IRQ control for each GPIO pin.
169.79 +
169.80 +Gpio_jz4730_irq_pin::Gpio_jz4730_irq_pin(unsigned pin, Hw::Register_block<32> const ®s)
169.81 +: _pin(pin), _regs(regs)
169.82 +{}
169.83 +
169.84 +void
169.85 +Gpio_jz4730_irq_pin::write_reg_pin(unsigned reg)
169.86 +{
169.87 + // Write the pin bit to the register, setting or clearing the pin
169.88 + // depending on the register chosen.
169.89 +
169.90 + _regs[reg] = _pin_bit(_pin);
169.91 +}
169.92 +
169.93 +void
169.94 +Gpio_jz4730_irq_pin::clear_reg_pin(unsigned reg)
169.95 +{
169.96 + // Clear the pin bit in the register.
169.97 +
169.98 + _regs[reg] = _regs[reg] & ~(_pin_bit(_pin));
169.99 +}
169.100 +
169.101 +void
169.102 +Gpio_jz4730_irq_pin::set_reg_pin(unsigned reg)
169.103 +{
169.104 + // Set the pin bit in the register.
169.105 +
169.106 + _regs[reg] = _regs[reg] | _pin_bit(_pin);
169.107 +}
169.108 +
169.109 +// Clear the pin bits in the appropriate register.
169.110 +
169.111 +void
169.112 +Gpio_jz4730_irq_pin::clear_reg_pins(uint32_t reg_upper, uint32_t reg_lower)
169.113 +{
169.114 + uint8_t pin_out;
169.115 + uint32_t reg = _select_bank_for_pin(reg_upper, reg_lower, _pin, &pin_out);
169.116 +
169.117 + _regs[reg] = _regs[reg] & ~(3 << (pin_out << 1));
169.118 +}
169.119 +
169.120 +// Clear and set the given value in the pin bits of the appropriate register.
169.121 +
169.122 +void
169.123 +Gpio_jz4730_irq_pin::set_reg_pins(uint32_t reg_upper, uint32_t reg_lower, uint8_t value)
169.124 +{
169.125 + uint8_t pin_out;
169.126 + uint32_t reg = _select_bank_for_pin(reg_upper, reg_lower, _pin, &pin_out);
169.127 +
169.128 + _regs[reg] = (_regs[reg] & ~(3 << (pin_out << 1))) | (value << (pin_out << 1));
169.129 +}
169.130 +
169.131 +void Gpio_jz4730_irq_pin::do_mask()
169.132 +{
169.133 + // Set the interrupt bit in the PxGPIER register.
169.134 +
169.135 + clear_reg_pin(Irq_enable);
169.136 +}
169.137 +
169.138 +void Gpio_jz4730_irq_pin::do_unmask()
169.139 +{
169.140 + // Set the interrupt bit in the PxGPIER register, first also clearing the
169.141 + // flag bit in the PxGPFR register to allow interrupts to be delivered.
169.142 +
169.143 + clear_reg_pin(Irq_flag);
169.144 + set_reg_pin(Irq_enable);
169.145 +}
169.146 +
169.147 +bool Gpio_jz4730_irq_pin::do_set_mode(unsigned mode)
169.148 +{
169.149 + // Standard comment found for this method:
169.150 + // this operation touches multiple mmio registers and is thus
169.151 + // not atomic, that's why we first mask the IRQ and if it was
169.152 + // enabled we unmask it after we have changed the mode
169.153 +
169.154 + if (enabled())
169.155 + do_mask();
169.156 +
169.157 + // Do the PxGPDUR/PxGPDLR configuration.
169.158 +
169.159 + switch(mode)
169.160 + {
169.161 + case L4_IRQ_F_LEVEL_HIGH:
169.162 + set_reg_pins(Irq_detect_upper, Irq_detect_lower, 1);
169.163 + break;
169.164 + case L4_IRQ_F_LEVEL_LOW:
169.165 + set_reg_pins(Irq_detect_upper, Irq_detect_lower, 0);
169.166 + break;
169.167 + case L4_IRQ_F_POS_EDGE:
169.168 + set_reg_pins(Irq_detect_upper, Irq_detect_lower, 3);
169.169 + break;
169.170 + case L4_IRQ_F_NEG_EDGE:
169.171 + set_reg_pins(Irq_detect_upper, Irq_detect_lower, 2);
169.172 + break;
169.173 +
169.174 + default:
169.175 + return false;
169.176 + }
169.177 +
169.178 + // Do the PxGPDIR, PxGPAUR/PxGPALR configuration.
169.179 +
169.180 + clear_reg_pin(Port_direction);
169.181 + clear_reg_pins(Port_function_upper, Port_function_lower);
169.182 +
169.183 + if (enabled())
169.184 + do_unmask();
169.185 +
169.186 + return true;
169.187 +}
169.188 +
169.189 +int Gpio_jz4730_irq_pin::clear()
169.190 +{
169.191 + // Obtain the flag status for the pin, clearing it if set.
169.192 +
169.193 + l4_uint32_t e = _regs[Irq_flag] & (1UL << _pin);
169.194 + if (e)
169.195 + clear_reg_pin(Irq_flag);
169.196 +
169.197 + return (e >> _pin);
169.198 +}
169.199 +
169.200 +bool Gpio_jz4730_irq_pin::enabled()
169.201 +{
169.202 + return true;
169.203 +}
169.204 +
169.205 +
169.206 +
169.207 +// Return two bitmaps for the given bitmap and value.
169.208 +
169.209 +static
169.210 +void
169.211 +_get_bitmaps(uint32_t bitmap, uint8_t value, uint32_t *upper, uint32_t *lower)
169.212 +{
169.213 + uint32_t mask = 0x80000000;
169.214 +
169.215 + *upper = 0; *lower = 0;
169.216 +
169.217 + while (mask != 0x8000)
169.218 + {
169.219 + *upper = (*upper << 2) | (bitmap & mask ? value : 0);
169.220 + mask >>= 1;
169.221 + }
169.222 +
169.223 + while (mask != 0)
169.224 + {
169.225 + *lower = (*lower << 2) | (bitmap & mask ? value : 0);
169.226 + mask >>= 1;
169.227 + }
169.228 +}
169.229 +
169.230 +
169.231 +
169.232 +// Initialise the GPIO controller.
169.233 +
169.234 +Gpio_jz4730_chip::Gpio_jz4730_chip(l4_addr_t start, l4_addr_t end,
169.235 + unsigned nr_pins)
169.236 +: _start(start), _end(end),
169.237 + _nr_pins(nr_pins)
169.238 +{
169.239 + _regs = new Hw::Mmio_register_block<32>(_start);
169.240 +}
169.241 +
169.242 +// Return the value of a pin.
169.243 +
169.244 +int
169.245 +Gpio_jz4730_chip::get(unsigned pin)
169.246 +{
169.247 + if (pin >= _nr_pins)
169.248 + throw -L4_EINVAL;
169.249 +
169.250 + l4_uint32_t val = _regs[Port_data];
169.251 + return (val >> _pin_shift(pin)) & 1;
169.252 +}
169.253 +
169.254 +// Return multiple pin values.
169.255 +
169.256 +unsigned
169.257 +Gpio_jz4730_chip::multi_get(unsigned offset)
169.258 +{
169.259 + _reg_offset_check(offset);
169.260 + return _regs[Port_data];
169.261 +}
169.262 +
169.263 +// Set the value of a pin.
169.264 +
169.265 +void
169.266 +Gpio_jz4730_chip::set(unsigned pin, int value)
169.267 +{
169.268 + if (pin >= _nr_pins)
169.269 + throw -L4_EINVAL;
169.270 +
169.271 + if (value)
169.272 + _regs[Port_data] = _regs[Port_data] | _pin_bit(pin);
169.273 + else
169.274 + _regs[Port_data] = _regs[Port_data] & ~_pin_bit(pin);
169.275 +}
169.276 +
169.277 +// Set multiple pin values.
169.278 +
169.279 +void
169.280 +Gpio_jz4730_chip::multi_set(Pin_slice const &mask, unsigned data)
169.281 +{
169.282 + _reg_offset_check(mask.offset);
169.283 + _regs[Port_data] = (_regs[Port_data] & ~(mask.mask)) | data;
169.284 +}
169.285 +
169.286 +// Set a pin up with the given mode and value (if appropriate).
169.287 +
169.288 +void
169.289 +Gpio_jz4730_chip::setup(unsigned pin, unsigned mode, int value)
169.290 +{
169.291 + if (pin >= _nr_pins)
169.292 + throw -L4_EINVAL;
169.293 +
169.294 + config(pin, mode);
169.295 +
169.296 + if (mode == Output)
169.297 + set(pin, value);
169.298 +}
169.299 +
169.300 +// Configuration of a pin using the generic input/output/IRQ mode.
169.301 +
169.302 +void
169.303 +Gpio_jz4730_chip::config(unsigned pin, unsigned mode)
169.304 +{
169.305 + _config(_pin_bit(pin), mode);
169.306 +}
169.307 +
169.308 +void
169.309 +Gpio_jz4730_chip::_config(unsigned bitmap, unsigned mode)
169.310 +{
169.311 + uint32_t upper_mask, lower_mask;
169.312 + unsigned bitmap_values = bitmap;
169.313 +
169.314 + switch (mode)
169.315 + {
169.316 + case Input:
169.317 + case Irq:
169.318 + // Clear the direction flags below.
169.319 + bitmap_values = 0;
169.320 + // Fall through to the next case to complete the operation.
169.321 +
169.322 + case Output:
169.323 + // Clear the flags if set immediately above; otherwise, set them.
169.324 + _regs[Port_direction] = (_regs[Port_direction] & ~bitmap) | bitmap_values;
169.325 +
169.326 + // Clear the port function for the bits.
169.327 + _get_bitmaps(bitmap, 3, &upper_mask, &lower_mask);
169.328 + _regs[Port_function_upper] = (_regs[Port_function_upper] & ~upper_mask);
169.329 + _regs[Port_function_lower] = (_regs[Port_function_lower] & ~lower_mask);
169.330 + break;
169.331 +
169.332 + default:
169.333 + break;
169.334 + }
169.335 +}
169.336 +
169.337 +// Pull-up configuration for a pin.
169.338 +
169.339 +void
169.340 +Gpio_jz4730_chip::config_pull(unsigned pin, unsigned mode)
169.341 +{
169.342 + if (pin >= _nr_pins)
169.343 + throw -L4_EINVAL;
169.344 +
169.345 + _config_pull(_pin_bit(pin), mode);
169.346 +}
169.347 +
169.348 +void
169.349 +Gpio_jz4730_chip::_config_pull(unsigned bitmap, unsigned mode)
169.350 +{
169.351 + switch (mode)
169.352 + {
169.353 + case Pull_none:
169.354 + _regs[Pull_enable] = _regs[Pull_enable] & ~bitmap;
169.355 + break;
169.356 + case Pull_up:
169.357 + _regs[Pull_enable] = _regs[Pull_enable] | bitmap;
169.358 + break;
169.359 + default:
169.360 + // Invalid pull-up/down mode for pin.
169.361 + throw -L4_EINVAL;
169.362 + }
169.363 +}
169.364 +
169.365 +// Pin function configuration.
169.366 +
169.367 +void
169.368 +Gpio_jz4730_chip::config_pad(unsigned pin, unsigned func, unsigned value)
169.369 +{
169.370 + if (pin >= _nr_pins)
169.371 + throw -L4_EINVAL;
169.372 +
169.373 + _config_pad(_pin_bit(pin), func, value);
169.374 +}
169.375 +
169.376 +void
169.377 +Gpio_jz4730_chip::_config_pad(unsigned bitmap, unsigned func, unsigned value)
169.378 +{
169.379 + uint32_t upper_mask = 0, lower_mask = 0, upper = 0, lower = 0;
169.380 +
169.381 + if (value > 3)
169.382 + throw -L4_EINVAL;
169.383 +
169.384 + switch (func)
169.385 + {
169.386 + case Hw::Gpio_chip::Function_alt:
169.387 + _get_bitmaps(bitmap, value, &upper, &lower);
169.388 + // Fall through to the next case to complete the operation.
169.389 +
169.390 + case Hw::Gpio_chip::Function_gpio:
169.391 + _get_bitmaps(bitmap, 3, &upper_mask, &lower_mask);
169.392 + _regs[Port_function_upper] = (_regs[Port_function_upper] & ~upper_mask) | upper;
169.393 + _regs[Port_function_lower] = (_regs[Port_function_lower] & ~lower_mask) | lower;
169.394 + break;
169.395 +
169.396 + default:
169.397 + throw -L4_EINVAL;
169.398 + }
169.399 +}
169.400 +
169.401 +// Obtain a pin's configuration from a register in the supplied value.
169.402 +
169.403 +void
169.404 +Gpio_jz4730_chip::config_get(unsigned pin, unsigned reg, unsigned *value)
169.405 +{
169.406 + if (pin >= _nr_pins)
169.407 + throw -L4_EINVAL;
169.408 +
169.409 + *value = (_regs[reg] >> _pin_shift(pin)) & 1;
169.410 +}
169.411 +
169.412 +// Obtain an IRQ abstraction for a pin.
169.413 +
169.414 +Hw::Gpio_irq_pin *
169.415 +Gpio_jz4730_chip::get_irq(unsigned pin)
169.416 +{
169.417 + if (pin >= _nr_pins)
169.418 + throw -L4_EINVAL;
169.419 +
169.420 + return new Gpio_jz4730_irq_pin(pin, _regs);
169.421 +}
169.422 +
169.423 +// Pull-up function configuration for multiple pins.
169.424 +
169.425 +void
169.426 +Gpio_jz4730_chip::multi_config_pull(Pin_slice const &mask, unsigned mode)
169.427 +{
169.428 + _config_pull(mask.mask << mask.offset, mode);
169.429 +}
169.430 +
169.431 +// Pin function configuration for multiple pins.
169.432 +
169.433 +void
169.434 +Gpio_jz4730_chip::multi_config_pad(Pin_slice const &mask, unsigned func, unsigned val)
169.435 +{
169.436 + _config_pad(mask.mask << mask.offset, func, val);
169.437 +}
169.438 +
169.439 +// Set up multiple pins with the given mode.
169.440 +
169.441 +void
169.442 +Gpio_jz4730_chip::multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues)
169.443 +{
169.444 + _config(mask.mask << mask.offset, mode);
169.445 +
169.446 + if (mode == Output)
169.447 + multi_set(mask, outvalues);
169.448 +}
169.449 +
169.450 +
169.451 +
169.452 +// C language interface functions.
169.453 +
169.454 +void *jz4730_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins)
169.455 +{
169.456 + return (void *) new Gpio_jz4730_chip(start, end, pins);
169.457 +}
169.458 +
169.459 +void jz4730_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
169.460 +{
169.461 + static_cast<Gpio_jz4730_chip *>(gpio)->setup(pin, mode, value);
169.462 +}
169.463 +
169.464 +void jz4730_gpio_config_pull(void *gpio, unsigned pin, unsigned mode)
169.465 +{
169.466 + static_cast<Gpio_jz4730_chip *>(gpio)->config_pull(pin, mode);
169.467 +}
169.468 +
169.469 +void jz4730_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value)
169.470 +{
169.471 + static_cast<Gpio_jz4730_chip *>(gpio)->config_pad(pin, func, value);
169.472 +}
169.473 +
169.474 +void jz4730_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value)
169.475 +{
169.476 + static_cast<Gpio_jz4730_chip *>(gpio)->config_get(pin, reg, value);
169.477 +}
169.478 +
169.479 +void jz4730_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues)
169.480 +{
169.481 + static_cast<Gpio_jz4730_chip *>(gpio)->multi_setup(*mask, mode, outvalues);
169.482 +}
169.483 +
169.484 +void jz4730_gpio_multi_config_pull(void *gpio, Pin_slice const *mask, unsigned mode)
169.485 +{
169.486 + static_cast<Gpio_jz4730_chip *>(gpio)->multi_config_pull(*mask, mode);
169.487 +}
169.488 +
169.489 +void jz4730_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value)
169.490 +{
169.491 + static_cast<Gpio_jz4730_chip *>(gpio)->multi_config_pad(*mask, func, value);
169.492 +}
169.493 +
169.494 +void jz4730_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data)
169.495 +{
169.496 + static_cast<Gpio_jz4730_chip *>(gpio)->multi_set(*mask, data);
169.497 +}
169.498 +
169.499 +unsigned jz4730_gpio_multi_get(void *gpio, unsigned offset)
169.500 +{
169.501 + return static_cast<Gpio_jz4730_chip *>(gpio)->multi_get(offset);
169.502 +}
169.503 +
169.504 +int jz4730_gpio_get(void *gpio, unsigned pin)
169.505 +{
169.506 + return static_cast<Gpio_jz4730_chip *>(gpio)->get(pin);
169.507 +}
169.508 +
169.509 +void jz4730_gpio_set(void *gpio, unsigned pin, int value)
169.510 +{
169.511 + static_cast<Gpio_jz4730_chip *>(gpio)->set(pin, value);
169.512 +}
169.513 +
169.514 +void *jz4730_gpio_get_irq(void *gpio, unsigned pin)
169.515 +{
169.516 + return (void *) static_cast<Gpio_jz4730_chip *>(gpio)->get_irq(pin);
169.517 +}
169.518 +
169.519 +bool jz4730_gpio_irq_set_mode(void *gpio_irq, unsigned mode)
169.520 +{
169.521 + return static_cast<Hw::Gpio_irq_pin *>(gpio_irq)->do_set_mode(mode);
169.522 +}
170.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
170.2 +++ b/pkg/devices/lib/gpio/src/jz4740.cc Sun May 13 01:34:16 2018 +0200
170.3 @@ -0,0 +1,452 @@
170.4 +/*
170.5 + * GPIO driver for Ingenic JZ4740.
170.6 + * (See below for additional copyright and licensing notices.)
170.7 + *
170.8 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
170.9 + *
170.10 + * This program is free software; you can redistribute it and/or
170.11 + * modify it under the terms of the GNU General Public License as
170.12 + * published by the Free Software Foundation; either version 2 of
170.13 + * the License, or (at your option) any later version.
170.14 + *
170.15 + * This program is distributed in the hope that it will be useful,
170.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
170.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
170.18 + * GNU General Public License for more details.
170.19 + *
170.20 + * You should have received a copy of the GNU General Public License
170.21 + * along with this program; if not, write to the Free Software
170.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
170.23 + * Boston, MA 02110-1301, USA
170.24 + *
170.25 + *
170.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
170.27 + * omap.cc GPIO driver implementations.
170.28 + *
170.29 + * This file is part of TUD:OS and distributed under the terms of the
170.30 + * GNU General Public License 2.
170.31 + * Please see the COPYING-GPL-2 file for details.
170.32 + */
170.33 +
170.34 +#include <l4/sys/icu.h>
170.35 +#include <l4/util/util.h>
170.36 +#include <l4/devices/hw_mmio_register_block.h>
170.37 +
170.38 +#include "gpio-jz4740.h"
170.39 +
170.40 +// GPIO register offsets (x in A..D).
170.41 +
170.42 +enum Regs
170.43 +{
170.44 + Pin_level = 0x000, // PxPIN (read-only)
170.45 + Port_data = 0x010, // PxDAT (read-only)
170.46 + Port_data_set = 0x014, // PxDATS
170.47 + Port_data_clear = 0x018, // PxDATC
170.48 + Irq_mask = 0x020, // PxIM (read-only)
170.49 + Irq_mask_set = 0x024, // PxIMS
170.50 + Irq_mask_clear = 0x028, // PxIMC
170.51 + Pull_disable = 0x030, // PxPE (read-only)
170.52 + Pull_disable_set = 0x034, // PxPES
170.53 + Pull_disable_clear = 0x038, // PxPEC
170.54 + Port_function = 0x040, // PxFUN (read-only)
170.55 + Port_function_set = 0x044, // PxFUNS
170.56 + Port_function_clear = 0x048, // PxFUNC
170.57 + Port_select = 0x050, // PxSEL (read-only)
170.58 + Port_select_set = 0x054, // PxSELS
170.59 + Port_select_clear = 0x058, // PxSELC
170.60 + Port_dir = 0x060, // PxDIR (read-only)
170.61 + Port_dir_set = 0x064, // PxDIRS
170.62 + Port_dir_clear = 0x068, // PxDIRC
170.63 + Port_trigger = 0x070, // PxTRG (read-only)
170.64 + Port_trigger_set = 0x074, // PxTRGS
170.65 + Port_trigger_clear = 0x078, // PxTRGC
170.66 + Irq_flag = 0x080, // PxFLG (read-only)
170.67 + Irq_flag_clear = 0x084, // PxFLGC
170.68 +};
170.69 +
170.70 +
170.71 +
170.72 +// IRQ control for each GPIO pin.
170.73 +
170.74 +Gpio_jz4740_irq_pin::Gpio_jz4740_irq_pin(unsigned pin, Hw::Register_block<32> const ®s)
170.75 +: _pin(pin), _regs(regs)
170.76 +{}
170.77 +
170.78 +void
170.79 +Gpio_jz4740_irq_pin::write_reg_pin(unsigned reg)
170.80 +{
170.81 + // Write the pin bit to the register, setting or clearing the pin
170.82 + // depending on the register chosen.
170.83 +
170.84 + _regs[reg] = _pin_bit(_pin);
170.85 +}
170.86 +
170.87 +void Gpio_jz4740_irq_pin::do_mask()
170.88 +{
170.89 + // Set the interrupt bit in the PxIM register.
170.90 +
170.91 + write_reg_pin(Irq_mask_set);
170.92 +}
170.93 +
170.94 +void Gpio_jz4740_irq_pin::do_unmask()
170.95 +{
170.96 + // Clear the interrupt bit in the PxIM register, first also clearing the
170.97 + // flag bit in the PxFLG register to allow interrupts to be delivered.
170.98 +
170.99 + write_reg_pin(Irq_flag_clear);
170.100 + write_reg_pin(Irq_mask_clear);
170.101 +}
170.102 +
170.103 +bool Gpio_jz4740_irq_pin::do_set_mode(unsigned mode)
170.104 +{
170.105 + // Standard comment found for this method:
170.106 + // this operation touches multiple mmio registers and is thus
170.107 + // not atomic, that's why we first mask the IRQ and if it was
170.108 + // enabled we unmask it after we have changed the mode
170.109 +
170.110 + if (enabled())
170.111 + do_mask();
170.112 +
170.113 + // Do the PxTRG, PxFUN, PxSEL and PxDIR configuration.
170.114 +
170.115 + switch(mode)
170.116 + {
170.117 + case L4_IRQ_F_LEVEL_HIGH:
170.118 + write_reg_pin(Port_trigger_clear);
170.119 + write_reg_pin(Port_function_clear);
170.120 + write_reg_pin(Port_select_set);
170.121 + write_reg_pin(Port_dir_set);
170.122 + break;
170.123 + case L4_IRQ_F_LEVEL_LOW:
170.124 + write_reg_pin(Port_trigger_clear);
170.125 + write_reg_pin(Port_function_clear);
170.126 + write_reg_pin(Port_select_set);
170.127 + write_reg_pin(Port_dir_clear);
170.128 + break;
170.129 + case L4_IRQ_F_POS_EDGE:
170.130 + write_reg_pin(Port_trigger_set);
170.131 + write_reg_pin(Port_function_clear);
170.132 + write_reg_pin(Port_select_set);
170.133 + write_reg_pin(Port_dir_set);
170.134 + break;
170.135 + case L4_IRQ_F_NEG_EDGE:
170.136 + write_reg_pin(Port_trigger_set);
170.137 + write_reg_pin(Port_function_clear);
170.138 + write_reg_pin(Port_select_set);
170.139 + write_reg_pin(Port_dir_clear);
170.140 + break;
170.141 +
170.142 + default:
170.143 + return false;
170.144 + }
170.145 +
170.146 + if (enabled())
170.147 + do_unmask();
170.148 +
170.149 + return true;
170.150 +}
170.151 +
170.152 +int Gpio_jz4740_irq_pin::clear()
170.153 +{
170.154 + // Obtain the flag status for the pin, clearing it if set.
170.155 +
170.156 + l4_uint32_t e = _regs[Irq_flag] & (1UL << _pin);
170.157 + if (e)
170.158 + _regs[Irq_flag_clear] = e;
170.159 +
170.160 + return (e >> _pin);
170.161 +}
170.162 +
170.163 +bool Gpio_jz4740_irq_pin::enabled()
170.164 +{
170.165 + return true;
170.166 +}
170.167 +
170.168 +
170.169 +
170.170 +// Initialise the GPIO controller.
170.171 +
170.172 +Gpio_jz4740_chip::Gpio_jz4740_chip(l4_addr_t start, l4_addr_t end,
170.173 + unsigned nr_pins)
170.174 +: _start(start), _end(end),
170.175 + _nr_pins(nr_pins)
170.176 +{
170.177 + _regs = new Hw::Mmio_register_block<32>(_start);
170.178 +}
170.179 +
170.180 +// Return the value of a pin.
170.181 +
170.182 +int
170.183 +Gpio_jz4740_chip::get(unsigned pin)
170.184 +{
170.185 + if (pin >= _nr_pins)
170.186 + throw -L4_EINVAL;
170.187 +
170.188 + l4_uint32_t val = _regs[Pin_level];
170.189 + return (val >> _pin_shift(pin)) & 1;
170.190 +}
170.191 +
170.192 +// Return multiple pin values.
170.193 +
170.194 +unsigned
170.195 +Gpio_jz4740_chip::multi_get(unsigned offset)
170.196 +{
170.197 + _reg_offset_check(offset);
170.198 + return _regs[Pin_level];
170.199 +}
170.200 +
170.201 +// Set the value of a pin.
170.202 +
170.203 +void
170.204 +Gpio_jz4740_chip::set(unsigned pin, int value)
170.205 +{
170.206 + if (pin >= _nr_pins)
170.207 + throw -L4_EINVAL;
170.208 +
170.209 + l4_uint32_t reg_set = value ? Port_data_set : Port_data_clear;
170.210 + _regs[reg_set] = _pin_bit(pin);
170.211 +}
170.212 +
170.213 +// Set multiple pin values.
170.214 +
170.215 +void
170.216 +Gpio_jz4740_chip::multi_set(Pin_slice const &mask, unsigned data)
170.217 +{
170.218 + _reg_offset_check(mask.offset);
170.219 + if (mask.mask & data)
170.220 + _regs[Port_data_set] = (mask.mask & data);
170.221 + if (mask.mask & ~data)
170.222 + _regs[Port_data_clear] = (mask.mask & ~data);
170.223 +}
170.224 +
170.225 +// Set a pin up with the given mode and value (if appropriate).
170.226 +
170.227 +void
170.228 +Gpio_jz4740_chip::setup(unsigned pin, unsigned mode, int value)
170.229 +{
170.230 + if (pin >= _nr_pins)
170.231 + throw -L4_EINVAL;
170.232 +
170.233 + config(pin, mode);
170.234 +
170.235 + if (mode == Output)
170.236 + set(pin, value);
170.237 +}
170.238 +
170.239 +// Configuration of a pin using the generic input/output/IRQ mode.
170.240 +
170.241 +void
170.242 +Gpio_jz4740_chip::config(unsigned pin, unsigned mode)
170.243 +{
170.244 + _config(_pin_bit(pin), mode);
170.245 +}
170.246 +
170.247 +void
170.248 +Gpio_jz4740_chip::_config(unsigned bitmap, unsigned mode)
170.249 +{
170.250 + switch (mode)
170.251 + {
170.252 + case Input:
170.253 + _regs[Port_function_clear] = bitmap;
170.254 + _regs[Port_select_clear] = bitmap;
170.255 + _regs[Port_dir_clear] = bitmap;
170.256 + break;
170.257 + case Output:
170.258 + _regs[Port_function_clear] = bitmap;
170.259 + _regs[Port_select_clear] = bitmap;
170.260 + _regs[Port_dir_set] = bitmap;
170.261 + break;
170.262 + case Irq:
170.263 + _regs[Port_function_clear] = bitmap;
170.264 + _regs[Port_select_set] = bitmap;
170.265 + // The direction depends on the actual trigger mode.
170.266 + break;
170.267 + default:
170.268 + break;
170.269 + }
170.270 +}
170.271 +
170.272 +// Pull-up configuration for a pin.
170.273 +
170.274 +void
170.275 +Gpio_jz4740_chip::config_pull(unsigned pin, unsigned mode)
170.276 +{
170.277 + if (pin >= _nr_pins)
170.278 + throw -L4_EINVAL;
170.279 +
170.280 + _config_pull(_pin_bit(pin), mode);
170.281 +}
170.282 +
170.283 +void
170.284 +Gpio_jz4740_chip::_config_pull(unsigned bitmap, unsigned mode)
170.285 +{
170.286 + switch (mode)
170.287 + {
170.288 + case Pull_none:
170.289 + _regs[Pull_disable_set] = bitmap;
170.290 + break;
170.291 + case Pull_up:
170.292 + _regs[Pull_disable_clear] = bitmap;
170.293 + break;
170.294 + default:
170.295 + // Invalid pull-up/down mode for pin.
170.296 + throw -L4_EINVAL;
170.297 + }
170.298 +}
170.299 +
170.300 +// Pin function configuration.
170.301 +
170.302 +void
170.303 +Gpio_jz4740_chip::config_pad(unsigned pin, unsigned func, unsigned value)
170.304 +{
170.305 + if (pin >= _nr_pins)
170.306 + throw -L4_EINVAL;
170.307 +
170.308 + _config_pad(_pin_bit(pin), func, value);
170.309 +}
170.310 +
170.311 +void
170.312 +Gpio_jz4740_chip::_config_pad(unsigned bitmap, unsigned func, unsigned value)
170.313 +{
170.314 + if (value > 1)
170.315 + throw -L4_EINVAL;
170.316 +
170.317 + switch (func)
170.318 + {
170.319 + case Hw::Gpio_chip::Function_gpio:
170.320 + _regs[Port_function_clear] = bitmap;
170.321 + break;
170.322 +
170.323 + // Support two different device functions.
170.324 +
170.325 + case Hw::Gpio_chip::Function_alt:
170.326 + _regs[Port_function_set] = bitmap;
170.327 + _regs[value ? Port_select_set : Port_select_clear] = bitmap;
170.328 + break;
170.329 + default:
170.330 + throw -L4_EINVAL;
170.331 + }
170.332 +}
170.333 +
170.334 +// Obtain a pin's configuration from a register in the supplied value.
170.335 +
170.336 +void
170.337 +Gpio_jz4740_chip::config_get(unsigned pin, unsigned reg, unsigned *value)
170.338 +{
170.339 + if (pin >= _nr_pins)
170.340 + throw -L4_EINVAL;
170.341 +
170.342 + *value = (_regs[reg] >> _pin_shift(pin)) & 1;
170.343 +}
170.344 +
170.345 +// Obtain an IRQ abstraction for a pin.
170.346 +
170.347 +Hw::Gpio_irq_pin *
170.348 +Gpio_jz4740_chip::get_irq(unsigned pin)
170.349 +{
170.350 + if (pin >= _nr_pins)
170.351 + throw -L4_EINVAL;
170.352 +
170.353 + return new Gpio_jz4740_irq_pin(pin, _regs);
170.354 +}
170.355 +
170.356 +// Pull-up function configuration for multiple pins.
170.357 +
170.358 +void
170.359 +Gpio_jz4740_chip::multi_config_pull(Pin_slice const &mask, unsigned mode)
170.360 +{
170.361 + _config_pull(mask.mask << mask.offset, mode);
170.362 +}
170.363 +
170.364 +// Pin function configuration for multiple pins.
170.365 +
170.366 +void
170.367 +Gpio_jz4740_chip::multi_config_pad(Pin_slice const &mask, unsigned func, unsigned val)
170.368 +{
170.369 + _config_pad(mask.mask << mask.offset, func, val);
170.370 +}
170.371 +
170.372 +// Set up multiple pins with the given mode.
170.373 +
170.374 +void
170.375 +Gpio_jz4740_chip::multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues)
170.376 +{
170.377 + _config(mask.mask << mask.offset, mode);
170.378 +
170.379 + if (mode == Output)
170.380 + multi_set(mask, outvalues);
170.381 +}
170.382 +
170.383 +
170.384 +
170.385 +// C language interface functions.
170.386 +
170.387 +void *jz4740_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins)
170.388 +{
170.389 + return (void *) new Gpio_jz4740_chip(start, end, pins);
170.390 +}
170.391 +
170.392 +void jz4740_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
170.393 +{
170.394 + static_cast<Gpio_jz4740_chip *>(gpio)->setup(pin, mode, value);
170.395 +}
170.396 +
170.397 +void jz4740_gpio_config_pull(void *gpio, unsigned pin, unsigned mode)
170.398 +{
170.399 + static_cast<Gpio_jz4740_chip *>(gpio)->config_pull(pin, mode);
170.400 +}
170.401 +
170.402 +void jz4740_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value)
170.403 +{
170.404 + static_cast<Gpio_jz4740_chip *>(gpio)->config_pad(pin, func, value);
170.405 +}
170.406 +
170.407 +void jz4740_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value)
170.408 +{
170.409 + static_cast<Gpio_jz4740_chip *>(gpio)->config_get(pin, reg, value);
170.410 +}
170.411 +
170.412 +void jz4740_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues)
170.413 +{
170.414 + static_cast<Gpio_jz4740_chip *>(gpio)->multi_setup(*mask, mode, outvalues);
170.415 +}
170.416 +
170.417 +void jz4740_gpio_multi_config_pull(void *gpio, Pin_slice const *mask, unsigned mode)
170.418 +{
170.419 + static_cast<Gpio_jz4740_chip *>(gpio)->multi_config_pull(*mask, mode);
170.420 +}
170.421 +
170.422 +void jz4740_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value)
170.423 +{
170.424 + static_cast<Gpio_jz4740_chip *>(gpio)->multi_config_pad(*mask, func, value);
170.425 +}
170.426 +
170.427 +void jz4740_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data)
170.428 +{
170.429 + static_cast<Gpio_jz4740_chip *>(gpio)->multi_set(*mask, data);
170.430 +}
170.431 +
170.432 +unsigned jz4740_gpio_multi_get(void *gpio, unsigned offset)
170.433 +{
170.434 + return static_cast<Gpio_jz4740_chip *>(gpio)->multi_get(offset);
170.435 +}
170.436 +
170.437 +int jz4740_gpio_get(void *gpio, unsigned pin)
170.438 +{
170.439 + return static_cast<Gpio_jz4740_chip *>(gpio)->get(pin);
170.440 +}
170.441 +
170.442 +void jz4740_gpio_set(void *gpio, unsigned pin, int value)
170.443 +{
170.444 + static_cast<Gpio_jz4740_chip *>(gpio)->set(pin, value);
170.445 +}
170.446 +
170.447 +void *jz4740_gpio_get_irq(void *gpio, unsigned pin)
170.448 +{
170.449 + return (void *) static_cast<Gpio_jz4740_chip *>(gpio)->get_irq(pin);
170.450 +}
170.451 +
170.452 +bool jz4740_gpio_irq_set_mode(void *gpio_irq, unsigned mode)
170.453 +{
170.454 + return static_cast<Hw::Gpio_irq_pin *>(gpio_irq)->do_set_mode(mode);
170.455 +}
171.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
171.2 +++ b/pkg/devices/lib/gpio/src/jz4780.cc Sun May 13 01:34:16 2018 +0200
171.3 @@ -0,0 +1,458 @@
171.4 +/*
171.5 + * GPIO driver for Ingenic JZ4780.
171.6 + * (See below for additional copyright and licensing notices.)
171.7 + *
171.8 + * (c) 2017 Paul Boddie <paul@boddie.org.uk>
171.9 + *
171.10 + * This program is free software; you can redistribute it and/or
171.11 + * modify it under the terms of the GNU General Public License as
171.12 + * published by the Free Software Foundation; either version 2 of
171.13 + * the License, or (at your option) any later version.
171.14 + *
171.15 + * This program is distributed in the hope that it will be useful,
171.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
171.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
171.18 + * GNU General Public License for more details.
171.19 + *
171.20 + * You should have received a copy of the GNU General Public License
171.21 + * along with this program; if not, write to the Free Software
171.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
171.23 + * Boston, MA 02110-1301, USA
171.24 + *
171.25 + *
171.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
171.27 + * omap.cc GPIO driver implementations.
171.28 + *
171.29 + * This file is part of TUD:OS and distributed under the terms of the
171.30 + * GNU General Public License 2.
171.31 + * Please see the COPYING-GPL-2 file for details.
171.32 + */
171.33 +
171.34 +#include <l4/sys/icu.h>
171.35 +#include <l4/util/util.h>
171.36 +#include <l4/devices/hw_mmio_register_block.h>
171.37 +
171.38 +#include "gpio-jz4780.h"
171.39 +
171.40 +/*
171.41 +GPIO register offsets (x in A..F).
171.42 +
171.43 +Register summary:
171.44 +
171.45 +PxINT 0 (function/GPIO) 1 (interrupt)
171.46 +PxMSK 0 (function) 1 (GPIO) 0 (IRQ enable)/1 (IRQ disable)
171.47 +PxPAT1 0 (function 0/1) 1 (function 2/3) 0 (output) 1 (input) 0 (level trigger) 1 (edge trigger)
171.48 +PxPAT0 0 (function 0) 0 (function 2) 0 (output value 0) 0 (low level) 0 (falling edge)
171.49 + 1 (function 1) 1 (function 3) 1 (output value 1) 1 (high level) 1 (rising edge)
171.50 +*/
171.51 +
171.52 +enum Regs
171.53 +{
171.54 + Pin_level = 0x000, // PxPIN (read-only)
171.55 +
171.56 + Port_int = 0x010, // PxINT
171.57 + Port_int_set = 0x014, // PxINTS
171.58 + Port_int_clear = 0x018, // PxINTC
171.59 +
171.60 + Irq_mask = 0x020, // PxMSK (for PxINT == 1)
171.61 + Irq_mask_set = 0x024, // PxMSKS
171.62 + Irq_mask_clear = 0x028, // PxMSKC
171.63 + Port_gpio = 0x020, // PxMSK (for PxINT == 0)
171.64 + Port_gpio_set = 0x024, // PxMSKS
171.65 + Port_gpio_clear = 0x028, // PxMSKC
171.66 +
171.67 + Port_trigger = 0x030, // PxPAT1 (for PxINT == 1)
171.68 + Port_trigger_set = 0x034, // PxPAT1S
171.69 + Port_trigger_clear = 0x038, // PxPAT1C
171.70 + Port_dir = 0x030, // PxPAT1 (for PxINT == 0, PxMSK == 1)
171.71 + Port_dir_set = 0x034, // PxPAT1S
171.72 + Port_dir_clear = 0x038, // PxPAT1C
171.73 + Port_group1 = 0x030, // PxPAT1 (for PxINT == 0, PxMSK == 0)
171.74 + Port_group1_set = 0x034, // PxPAT1S
171.75 + Port_group1_clear = 0x038, // PxPAT1C
171.76 +
171.77 + Port_level = 0x040, // PxPAT0 (for PxINT == 1)
171.78 + Port_level_set = 0x044, // PxPAT0S
171.79 + Port_level_clear = 0x048, // PxPAT0C
171.80 + Port_data = 0x040, // PxPAT0 (for PxINT == 0, PxMSK == 1, PxPAT1 == 0)
171.81 + Port_data_set = 0x044, // PxPAT0S
171.82 + Port_data_clear = 0x048, // PxPAT0C
171.83 + Port_group0 = 0x040, // PxPAT0 (for PxINT == 0, PxMSK == 0)
171.84 + Port_group0_set = 0x044, // PxPAT0S
171.85 + Port_group0_clear = 0x048, // PxPAT0C
171.86 +
171.87 + Irq_flag = 0x050, // PxFLG (read-only)
171.88 + Irq_flag_clear = 0x058, // PxFLGC
171.89 +
171.90 + Pull_disable = 0x070, // PxPE
171.91 + Pull_disable_set = 0x074, // PxPES
171.92 + Pull_disable_clear = 0x078, // PxPEC
171.93 +};
171.94 +
171.95 +
171.96 +
171.97 +// IRQ control for each GPIO pin.
171.98 +
171.99 +Gpio_jz4780_irq_pin::Gpio_jz4780_irq_pin(unsigned pin, Hw::Register_block<32> const ®s)
171.100 +: _pin(pin), _regs(regs)
171.101 +{}
171.102 +
171.103 +void
171.104 +Gpio_jz4780_irq_pin::write_reg_pin(unsigned reg)
171.105 +{
171.106 + // Write the pin bit to the register, setting or clearing the pin
171.107 + // depending on the register chosen.
171.108 +
171.109 + _regs[reg] = _pin_bit(_pin);
171.110 +}
171.111 +
171.112 +void Gpio_jz4780_irq_pin::do_mask()
171.113 +{
171.114 + // Set the interrupt bit in the PxIM register.
171.115 +
171.116 + write_reg_pin(Irq_mask_set);
171.117 +}
171.118 +
171.119 +void Gpio_jz4780_irq_pin::do_unmask()
171.120 +{
171.121 + // Clear the interrupt bit in the PxIM register, first also clearing the
171.122 + // flag bit in the PxFLG register to allow interrupts to be delivered.
171.123 +
171.124 + write_reg_pin(Irq_flag_clear);
171.125 + write_reg_pin(Irq_mask_clear);
171.126 +}
171.127 +
171.128 +bool Gpio_jz4780_irq_pin::do_set_mode(unsigned mode)
171.129 +{
171.130 + // Standard comment found for this method:
171.131 + // this operation touches multiple mmio registers and is thus
171.132 + // not atomic, that's why we first mask the IRQ and if it was
171.133 + // enabled we unmask it after we have changed the mode
171.134 +
171.135 + if (enabled())
171.136 + do_mask();
171.137 +
171.138 + // Do the PxINT, PxPAT1 and PxPAT0 configuration.
171.139 +
171.140 + switch(mode)
171.141 + {
171.142 + case L4_IRQ_F_LEVEL_HIGH:
171.143 + write_reg_pin(Port_int_set);
171.144 + write_reg_pin(Port_trigger_clear);
171.145 + write_reg_pin(Port_level_set);
171.146 + break;
171.147 + case L4_IRQ_F_LEVEL_LOW:
171.148 + write_reg_pin(Port_int_set);
171.149 + write_reg_pin(Port_trigger_clear);
171.150 + write_reg_pin(Port_level_clear);
171.151 + break;
171.152 + case L4_IRQ_F_POS_EDGE:
171.153 + write_reg_pin(Port_int_set);
171.154 + write_reg_pin(Port_trigger_set);
171.155 + write_reg_pin(Port_level_set);
171.156 + break;
171.157 + case L4_IRQ_F_NEG_EDGE:
171.158 + write_reg_pin(Port_int_set);
171.159 + write_reg_pin(Port_trigger_set);
171.160 + write_reg_pin(Port_level_clear);
171.161 + break;
171.162 +
171.163 + default:
171.164 + return false;
171.165 + }
171.166 +
171.167 + if (enabled())
171.168 + do_unmask();
171.169 +
171.170 + return true;
171.171 +}
171.172 +
171.173 +int Gpio_jz4780_irq_pin::clear()
171.174 +{
171.175 + // Obtain the flag status for the pin, clearing it if set.
171.176 +
171.177 + l4_uint32_t e = _regs[Irq_flag] & (1UL << _pin);
171.178 + if (e)
171.179 + _regs[Irq_flag_clear] = e;
171.180 +
171.181 + return (e >> _pin);
171.182 +}
171.183 +
171.184 +bool Gpio_jz4780_irq_pin::enabled()
171.185 +{
171.186 + return true;
171.187 +}
171.188 +
171.189 +
171.190 +
171.191 +// Initialise the GPIO controller.
171.192 +
171.193 +Gpio_jz4780_chip::Gpio_jz4780_chip(l4_addr_t start, l4_addr_t end,
171.194 + unsigned nr_pins,
171.195 + l4_uint32_t pull_ups, l4_uint32_t pull_downs)
171.196 +: _start(start), _end(end),
171.197 + _nr_pins(nr_pins),
171.198 + _pull_ups(pull_ups), _pull_downs(pull_downs)
171.199 +{
171.200 + _regs = new Hw::Mmio_register_block<32>(_start);
171.201 +}
171.202 +
171.203 +// Return the value of a pin.
171.204 +
171.205 +int
171.206 +Gpio_jz4780_chip::get(unsigned pin)
171.207 +{
171.208 + if (pin >= _nr_pins)
171.209 + throw -L4_EINVAL;
171.210 +
171.211 + l4_uint32_t val = _regs[Pin_level];
171.212 + return (val >> _pin_shift(pin)) & 1;
171.213 +}
171.214 +
171.215 +// Return multiple pin values.
171.216 +
171.217 +unsigned
171.218 +Gpio_jz4780_chip::multi_get(unsigned offset)
171.219 +{
171.220 + _reg_offset_check(offset);
171.221 + return _regs[Pin_level];
171.222 +}
171.223 +
171.224 +// Set the value of a pin.
171.225 +
171.226 +void
171.227 +Gpio_jz4780_chip::set(unsigned pin, int value)
171.228 +{
171.229 + if (pin >= _nr_pins)
171.230 + throw -L4_EINVAL;
171.231 +
171.232 + l4_uint32_t reg_set = value ? Port_data_set : Port_data_clear;
171.233 + _regs[reg_set] = _pin_bit(pin);
171.234 +}
171.235 +
171.236 +// Set multiple pin values.
171.237 +
171.238 +void
171.239 +Gpio_jz4780_chip::multi_set(Pin_slice const &mask, unsigned data)
171.240 +{
171.241 + _reg_offset_check(mask.offset);
171.242 + if (mask.mask & data)
171.243 + _regs[Port_data_set] = (mask.mask & data);
171.244 + if (mask.mask & ~data)
171.245 + _regs[Port_data_clear] = (mask.mask & ~data);
171.246 +}
171.247 +
171.248 +// Set a pin up with the given mode and value (if appropriate).
171.249 +
171.250 +void
171.251 +Gpio_jz4780_chip::setup(unsigned pin, unsigned mode, int value)
171.252 +{
171.253 + if (pin >= _nr_pins)
171.254 + throw -L4_EINVAL;
171.255 +
171.256 + config(pin, mode);
171.257 +
171.258 + if (mode == Output)
171.259 + set(pin, value);
171.260 +}
171.261 +
171.262 +// Configuration of a pin using the generic input/output/IRQ mode.
171.263 +
171.264 +void
171.265 +Gpio_jz4780_chip::config(unsigned pin, unsigned mode)
171.266 +{
171.267 + switch (mode)
171.268 + {
171.269 + case Input:
171.270 + _regs[Port_int_clear] = _pin_bit(pin);
171.271 + _regs[Port_gpio_set] = _pin_bit(pin);
171.272 + _regs[Port_dir_set] = _pin_bit(pin);
171.273 + break;
171.274 + case Output:
171.275 + _regs[Port_int_clear] = _pin_bit(pin);
171.276 + _regs[Port_gpio_set] = _pin_bit(pin);
171.277 + _regs[Port_dir_clear] = _pin_bit(pin);
171.278 + break;
171.279 + case Irq:
171.280 + _regs[Port_int_set] = _pin_bit(pin);
171.281 + // Other details depend on the actual trigger mode.
171.282 + break;
171.283 + default:
171.284 + break;
171.285 + }
171.286 +}
171.287 +
171.288 +// Pull-up/down configuration for a pin.
171.289 +
171.290 +void
171.291 +Gpio_jz4780_chip::config_pull(unsigned pin, unsigned mode)
171.292 +{
171.293 + if (pin >= _nr_pins)
171.294 + throw -L4_EINVAL;
171.295 +
171.296 + switch (mode)
171.297 + {
171.298 + case Pull_none:
171.299 + _regs[Pull_disable_set] = _pin_bit(pin);
171.300 + break;
171.301 + case Pull_down:
171.302 + if (_pin_bit(pin) & _pull_downs)
171.303 + _regs[Pull_disable_clear] = _pin_bit(pin);
171.304 + break;
171.305 + case Pull_up:
171.306 + if (_pin_bit(pin) & _pull_ups)
171.307 + _regs[Pull_disable_clear] = _pin_bit(pin);
171.308 + break;
171.309 + default:
171.310 + // Invalid pull-up/down mode for pin.
171.311 + throw -L4_EINVAL;
171.312 + }
171.313 +}
171.314 +
171.315 +// Pin function configuration.
171.316 +
171.317 +void
171.318 +Gpio_jz4780_chip::config_pad(unsigned pin, unsigned func, unsigned value)
171.319 +{
171.320 + if (pin >= _nr_pins)
171.321 + throw -L4_EINVAL;
171.322 +
171.323 + if (value > 1)
171.324 + throw -L4_EINVAL;
171.325 +
171.326 + switch (func)
171.327 + {
171.328 + // Support two different outputs.
171.329 +
171.330 + case Hw::Gpio_chip::Function_gpio:
171.331 + _regs[Port_int_clear] = _pin_bit(pin);
171.332 + _regs[Port_gpio_set] = _pin_bit(pin);
171.333 + _regs[value & 1 ? Port_data_set : Port_data_clear] = _pin_bit(pin);
171.334 + break;
171.335 +
171.336 + // Support four different device functions.
171.337 +
171.338 + case Hw::Gpio_chip::Function_alt:
171.339 + _regs[Port_int_clear] = _pin_bit(pin);
171.340 + _regs[Port_gpio_clear] = _pin_bit(pin);
171.341 + _regs[value & 2 ? Port_group1_set : Port_group1_clear] = _pin_bit(pin);
171.342 + _regs[value & 1 ? Port_group0_set : Port_group0_clear] = _pin_bit(pin);
171.343 + break;
171.344 + default:
171.345 + throw -L4_EINVAL;
171.346 + }
171.347 +}
171.348 +
171.349 +// Obtain a pin's configuration from a register in the supplied value.
171.350 +
171.351 +void
171.352 +Gpio_jz4780_chip::config_get(unsigned pin, unsigned reg, unsigned *value)
171.353 +{
171.354 + if (pin >= _nr_pins)
171.355 + throw -L4_EINVAL;
171.356 +
171.357 + *value = (_regs[reg] >> _pin_shift(pin)) & 1;
171.358 +}
171.359 +
171.360 +// Obtain an IRQ abstraction for a pin.
171.361 +
171.362 +Hw::Gpio_irq_pin *
171.363 +Gpio_jz4780_chip::get_irq(unsigned pin)
171.364 +{
171.365 + if (pin >= _nr_pins)
171.366 + throw -L4_EINVAL;
171.367 +
171.368 + return new Gpio_jz4780_irq_pin(pin, _regs);
171.369 +}
171.370 +
171.371 +// Pin function configuration for multiple pins.
171.372 +
171.373 +void
171.374 +Gpio_jz4780_chip::multi_config_pad(Pin_slice const &mask, unsigned func, unsigned val)
171.375 +{
171.376 + unsigned m = mask.mask;
171.377 + for (unsigned pin = mask.offset; pin < _nr_pins; ++pin, m >>= 1)
171.378 + if (m & 1)
171.379 + config_pad(pin, func, val);
171.380 +}
171.381 +
171.382 +// Set up multiple pins with the given mode.
171.383 +
171.384 +void
171.385 +Gpio_jz4780_chip::multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues)
171.386 +{
171.387 + unsigned m = mask.mask;
171.388 + for (unsigned pin = mask.offset; pin < _nr_pins; ++pin, m >>= 1, outvalues >>= 1)
171.389 + if (m & 1)
171.390 + setup(pin, mode, outvalues & 1);
171.391 +}
171.392 +
171.393 +
171.394 +
171.395 +// C language interface functions.
171.396 +
171.397 +void *jz4780_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
171.398 + l4_uint32_t pull_ups, l4_uint32_t pull_downs)
171.399 +{
171.400 + return (void *) new Gpio_jz4780_chip(start, end, pins, pull_ups, pull_downs);
171.401 +}
171.402 +
171.403 +void jz4780_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
171.404 +{
171.405 + static_cast<Gpio_jz4780_chip *>(gpio)->setup(pin, mode, value);
171.406 +}
171.407 +
171.408 +void jz4780_gpio_config_pull(void *gpio, unsigned pin, unsigned mode)
171.409 +{
171.410 + static_cast<Gpio_jz4780_chip *>(gpio)->config_pull(pin, mode);
171.411 +}
171.412 +
171.413 +void jz4780_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value)
171.414 +{
171.415 + static_cast<Gpio_jz4780_chip *>(gpio)->config_pad(pin, func, value);
171.416 +}
171.417 +
171.418 +void jz4780_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value)
171.419 +{
171.420 + static_cast<Gpio_jz4780_chip *>(gpio)->config_get(pin, reg, value);
171.421 +}
171.422 +
171.423 +void jz4780_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues)
171.424 +{
171.425 + static_cast<Gpio_jz4780_chip *>(gpio)->multi_setup(*mask, mode, outvalues);
171.426 +}
171.427 +
171.428 +void jz4780_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value)
171.429 +{
171.430 + static_cast<Gpio_jz4780_chip *>(gpio)->multi_config_pad(*mask, func, value);
171.431 +}
171.432 +
171.433 +void jz4780_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data)
171.434 +{
171.435 + static_cast<Gpio_jz4780_chip *>(gpio)->multi_set(*mask, data);
171.436 +}
171.437 +
171.438 +unsigned jz4780_gpio_multi_get(void *gpio, unsigned offset)
171.439 +{
171.440 + return static_cast<Gpio_jz4780_chip *>(gpio)->multi_get(offset);
171.441 +}
171.442 +
171.443 +int jz4780_gpio_get(void *gpio, unsigned pin)
171.444 +{
171.445 + return static_cast<Gpio_jz4780_chip *>(gpio)->get(pin);
171.446 +}
171.447 +
171.448 +void jz4780_gpio_set(void *gpio, unsigned pin, int value)
171.449 +{
171.450 + static_cast<Gpio_jz4780_chip *>(gpio)->set(pin, value);
171.451 +}
171.452 +
171.453 +void *jz4780_gpio_get_irq(void *gpio, unsigned pin)
171.454 +{
171.455 + return (void *) static_cast<Gpio_jz4780_chip *>(gpio)->get_irq(pin);
171.456 +}
171.457 +
171.458 +bool jz4780_gpio_irq_set_mode(void *gpio_irq, unsigned mode)
171.459 +{
171.460 + return static_cast<Hw::Gpio_irq_pin *>(gpio_irq)->do_set_mode(mode);
171.461 +}
172.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
172.2 +++ b/pkg/devices/lib/i2c/Makefile Sun May 13 01:34:16 2018 +0200
172.3 @@ -0,0 +1,8 @@
172.4 +PKGDIR ?= ../..
172.5 +L4DIR ?= $(PKGDIR)/../..
172.6 +
172.7 +TARGET := include src
172.8 +
172.9 +include $(L4DIR)/mk/subdir.mk
172.10 +
172.11 +src: include
173.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
173.2 +++ b/pkg/devices/lib/i2c/include/Makefile Sun May 13 01:34:16 2018 +0200
173.3 @@ -0,0 +1,4 @@
173.4 +PKGDIR = ../../..
173.5 +L4DIR ?= $(PKGDIR)/../..
173.6 +
173.7 +include $(L4DIR)/mk/include.mk
174.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
174.2 +++ b/pkg/devices/lib/i2c/include/i2c-jz4780.h Sun May 13 01:34:16 2018 +0200
174.3 @@ -0,0 +1,116 @@
174.4 +/*
174.5 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
174.6 + *
174.7 + * This program is free software; you can redistribute it and/or
174.8 + * modify it under the terms of the GNU General Public License as
174.9 + * published by the Free Software Foundation; either version 2 of
174.10 + * the License, or (at your option) any later version.
174.11 + *
174.12 + * This program is distributed in the hope that it will be useful,
174.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
174.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
174.15 + * GNU General Public License for more details.
174.16 + *
174.17 + * You should have received a copy of the GNU General Public License
174.18 + * along with this program; if not, write to the Free Software
174.19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
174.20 + * Boston, MA 02110-1301, USA
174.21 + */
174.22 +
174.23 +#pragma once
174.24 +
174.25 +#include <l4/sys/types.h>
174.26 +#include <stdint.h>
174.27 +
174.28 +
174.29 +
174.30 +#ifdef __cplusplus
174.31 +
174.32 +#include <l4/devices/cpm-jz4780.h>
174.33 +#include <l4/devices/hw_mmio_register_block.h>
174.34 +
174.35 +// I2C channel.
174.36 +
174.37 +class I2c_jz4780_channel
174.38 +{
174.39 +private:
174.40 + Hw::Register_block<32> _regs;
174.41 + Cpm_jz4780_chip *_cpm;
174.42 + uint32_t _frequency;
174.43 + unsigned queued, _pos, _reqpos, _total;
174.44 + uint8_t *_buf;
174.45 + int _fail, _stop, _last;
174.46 +
174.47 +public:
174.48 + I2c_jz4780_channel(l4_addr_t start, Cpm_jz4780_chip *cpm,
174.49 + uint32_t frequency);
174.50 +
174.51 + void set_target(uint8_t addr);
174.52 + void start_read(uint8_t buf[], unsigned total);
174.53 + void read();
174.54 + int read_done();
174.55 + unsigned have_read();
174.56 + int read_incomplete();
174.57 + void write(uint8_t buf[], unsigned total);
174.58 + void stop();
174.59 +
174.60 +private:
174.61 + void disable();
174.62 + void enable();
174.63 +
174.64 + int active();
174.65 + int have_input();
174.66 + int have_output();
174.67 + int can_send();
174.68 + int read_failed();
174.69 + int write_failed();
174.70 +
174.71 + void reset_flags();
174.72 + void init_parameters();
174.73 + void set_frequency();
174.74 +
174.75 + void set_read_threshold();
174.76 + void queue_reads();
174.77 + void queue_writes(uint8_t buf[], unsigned *pos, unsigned total);
174.78 + void store_reads();
174.79 +};
174.80 +
174.81 +// I2C device control.
174.82 +
174.83 +class I2c_jz4780_chip
174.84 +{
174.85 +private:
174.86 + l4_addr_t _start, _end;
174.87 + Cpm_jz4780_chip *_cpm;
174.88 + uint32_t _frequency;
174.89 +
174.90 +public:
174.91 + I2c_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm,
174.92 + uint32_t frequency);
174.93 +
174.94 + I2c_jz4780_channel *get_channel(uint8_t channel);
174.95 +};
174.96 +
174.97 +#endif /* __cplusplus */
174.98 +
174.99 +
174.100 +
174.101 +/* C language interface. */
174.102 +
174.103 +EXTERN_C_BEGIN
174.104 +
174.105 +void *jz4780_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm,
174.106 + uint32_t frequency);
174.107 +
174.108 +void *jz4780_i2c_get_channel(void *i2c, uint8_t channel);
174.109 +
174.110 +void jz4780_i2c_set_target(void *i2c_channel, uint8_t addr);
174.111 +void jz4780_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned total);
174.112 +void jz4780_i2c_read(void *i2c_channel);
174.113 +int jz4780_i2c_read_done(void *i2c_channel);
174.114 +unsigned jz4780_i2c_have_read(void *i2c_channel);
174.115 +int jz4780_i2c_read_incomplete(void *i2c_channel);
174.116 +void jz4780_i2c_write(void *i2c_channel, uint8_t buf[], unsigned total);
174.117 +void jz4780_i2c_stop(void *i2c_channel);
174.118 +
174.119 +EXTERN_C_END
175.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
175.2 +++ b/pkg/devices/lib/i2c/src/Makefile Sun May 13 01:34:16 2018 +0200
175.3 @@ -0,0 +1,13 @@
175.4 +PKGDIR ?= ../../..
175.5 +L4DIR ?= $(PKGDIR)/../..
175.6 +
175.7 +TARGET = libi2c.o.a
175.8 +PC_FILENAME := libdrivers-i2c
175.9 +
175.10 +SRC_CC := jz4780.cc
175.11 +
175.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/i2c/include
175.13 +
175.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common
175.15 +
175.16 +include $(L4DIR)/mk/lib.mk
176.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
176.2 +++ b/pkg/devices/lib/i2c/src/jz4780.cc Sun May 13 01:34:16 2018 +0200
176.3 @@ -0,0 +1,693 @@
176.4 +/*
176.5 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
176.6 + *
176.7 + * This program is free software; you can redistribute it and/or
176.8 + * modify it under the terms of the GNU General Public License as
176.9 + * published by the Free Software Foundation; either version 2 of
176.10 + * the License, or (at your option) any later version.
176.11 + *
176.12 + * This program is distributed in the hope that it will be useful,
176.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
176.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
176.15 + * GNU General Public License for more details.
176.16 + *
176.17 + * You should have received a copy of the GNU General Public License
176.18 + * along with this program; if not, write to the Free Software
176.19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
176.20 + * Boston, MA 02110-1301, USA
176.21 + */
176.22 +
176.23 +#include <l4/devices/i2c-jz4780.h>
176.24 +#include <l4/devices/hw_mmio_register_block.h>
176.25 +
176.26 +#include <l4/sys/icu.h>
176.27 +#include <l4/util/util.h>
176.28 +#include <sys/time.h>
176.29 +
176.30 +#include <cstdio>
176.31 +
176.32 +/*
176.33 +I2C pins:
176.34 +
176.35 +I2C0: PD30/SMB0_SDA, PD31/SMB0_SCK
176.36 +I2C1: PD30/SMB1_SDA, PD31/SMB1_SCK (pulled up on CI20)
176.37 +I2C2: PF16/SMB2_SDA, PF17/SMB2_SCK
176.38 + PWM: PD10/SMB3_SDA, PD11/SMB3_SCK
176.39 + PWM: PE3/SMB4_SDA, PE4/SMB4_SCK
176.40 +I2C4: PE12/SMB4_SDA, PE13/SMB4_SCK
176.41 +HDMI: PF25/SMB4_SDA/DDCSDA, PF24/SMB4_SCK/DDCSCK
176.42 +
176.43 +See: http://mipscreator.imgtec.com/CI20/hardware/board/ci20_jz4780_v2.0.pdf
176.44 +*/
176.45 +
176.46 +enum Regs
176.47 +{
176.48 + Smb_control = 0x000, // SMBCON
176.49 + Smb_target_address = 0x004, // SMBTAR
176.50 + Smb_slave_address = 0x008, // SMBSAR
176.51 + Smb_data_command = 0x010, // SMBDC
176.52 + Std_high_count = 0x014, // SMBSHCNT
176.53 + Std_low_count = 0x018, // SMBSLCNT
176.54 + Fast_high_count = 0x01c, // SMBFHCNT
176.55 + Fast_low_count = 0x020, // SMBFLCNT
176.56 + Int_status = 0x02c, // SMBINTST (read-only)
176.57 + Int_mask = 0x030, // SMBINTM
176.58 +
176.59 + Rx_fifo_thold = 0x038, // SMBRXTL
176.60 + Tx_fifo_thold = 0x03c, // SMBTXTL
176.61 + Int_combined_clear = 0x040, // SMBCINT (read-only)
176.62 + Int_rx_uf_clear = 0x044, // SMBCRXUF (read-only)
176.63 + Int_rx_of_clear = 0x048, // SMBCRXOF (read-only)
176.64 + Int_tx_of_clear = 0x04c, // SMBCTXOF (read-only)
176.65 + Int_rd_req_clear = 0x050, // SMBCRXREQ (read-only)
176.66 + Int_tx_abort_clear = 0x054, // SMBCTXABT (read-only)
176.67 + Int_rx_done_clear = 0x058, // SMBCRXDN (read-only)
176.68 + Int_activity_clear = 0x05c, // SMBCACT (read-only)
176.69 + Int_stop_clear = 0x060, // SMBCSTP (read-only)
176.70 + Int_start_clear = 0x064, // SMBCSTT (read-only)
176.71 + Int_call_clear = 0x068, // SMBCGC (read-only)
176.72 + Smb_enable = 0x06c, // SMBENB
176.73 + Smb_status = 0x070, // SMBST (read-only)
176.74 +
176.75 + Tx_fifo_count = 0x074, // SMBTXFLR (read-only)
176.76 + Rx_fifo_count = 0x078, // SMBRXFLR (read-only)
176.77 +
176.78 + Trans_abort_status0 = 0x080, // SMBABTSRC (read-only)
176.79 + Trans_abort_status1 = 0x084, // ... (read-only)
176.80 +
176.81 + Smb_dma_ctrl = 0x088, // SMBDMACR
176.82 + Smb_trans_data_lvl = 0x08c, // SMBDMATDLR
176.83 + Smb_recv_data_lvl = 0x090, // SMBDMARDLR
176.84 + Smb_sda_setup_time = 0x094, // SMBSDASU
176.85 + Smb_ack_call = 0x098, // SMBACKGC
176.86 +
176.87 + Smb_enable_status = 0x09c, // SMBENBST (read-only)
176.88 + Smb_sda_hold_time = 0x0d0, // SMBSDAHD
176.89 +
176.90 + Smb_block_offset = 0x1000
176.91 +};
176.92 +
176.93 +enum Smb_control_bits : unsigned
176.94 +{
176.95 + Smb_no_stop_empty = 0x80, // STPHLD (no STP condition when queue empty)
176.96 + Smb_disable_slave = 0x40, // SLVDIS (slave disabled)
176.97 + Smb_enable_restart = 0x20, // REST
176.98 + Smb_enable_master = 0x01, // MD (master enabled)
176.99 + Smb_speed_bit = 1, // SPD
176.100 +};
176.101 +
176.102 +enum Smb_enable_bits : unsigned
176.103 +{
176.104 + Smb_enable_enabled = 0x01, // SMBEN
176.105 +};
176.106 +
176.107 +enum Smb_status_bits : unsigned
176.108 +{
176.109 + Smb_status_master_act = 0x20, // MSTACT (master active)
176.110 + Smb_status_rx_nempty = 0x08, // RFNE (read queue not empty)
176.111 + Smb_status_tx_empty = 0x04, // TFE (write queue empty)
176.112 + Smb_status_tx_nfull = 0x02, // TFNF (write queue not full)
176.113 + Smb_status_active = 0x01, // ACT (device active as master or slave)
176.114 +};
176.115 +
176.116 +enum Smb_target_bits : unsigned
176.117 +{
176.118 + Smb_target_7bits = 0x7f,
176.119 +};
176.120 +
176.121 +enum Smb_hold_control_bits : unsigned
176.122 +{
176.123 + Smb_hold_enable = 0x100, // HDENB
176.124 + Smb_hold_disable = 0x000, // HDENB
176.125 + Smb_hold_mask = 0x1ff,
176.126 +};
176.127 +
176.128 +enum Smb_setup_control_bits : unsigned
176.129 +{
176.130 + Smb_setup_mask = 0x0ff,
176.131 +};
176.132 +
176.133 +enum Smb_command_bits : unsigned
176.134 +{
176.135 + Smb_command_read = 0x100, // CMD
176.136 + Smb_command_write = 0x000, // CMD
176.137 +};
176.138 +
176.139 +enum Smb_fifo_bits : unsigned
176.140 +{
176.141 + Smb_fifo_limit = 16,
176.142 +};
176.143 +
176.144 +enum Int_bits : unsigned
176.145 +{
176.146 + Int_call = 0x800, // IGC (general call received)
176.147 + Int_start = 0x400, // ISTT (start/restart condition occurred)
176.148 + Int_stop = 0x200, // ISTP (stop condition occurred)
176.149 + Int_activity = 0x100, // IACT (bus activity interrupt)
176.150 + Int_rx_done = 0x080, // RXDN (read from master device done)
176.151 + Int_tx_abort = 0x040, // TXABT (transmit abort)
176.152 + Int_rd_req = 0x020, // RDREQ (read request from master device)
176.153 + Int_tx_empty = 0x010, // TXEMP (threshold reached or passed)
176.154 + Int_tx_of = 0x008, // TXOF (overflow when writing to queue)
176.155 + Int_rx_full = 0x004, // RXFL (threshold reached or exceeded)
176.156 + Int_rx_of = 0x002, // RXOF (overflow from device)
176.157 + Int_rx_uf = 0x001, // RXUF (underflow when reading from queue)
176.158 +};
176.159 +
176.160 +
176.161 +
176.162 +// Initialise a channel.
176.163 +
176.164 +I2c_jz4780_channel::I2c_jz4780_channel(l4_addr_t start,
176.165 + Cpm_jz4780_chip *cpm,
176.166 + uint32_t frequency)
176.167 +: _cpm(cpm), _frequency(frequency)
176.168 +{
176.169 + _regs = new Hw::Mmio_register_block<32>(start);
176.170 +}
176.171 +
176.172 +// Enable the channel.
176.173 +
176.174 +void
176.175 +I2c_jz4780_channel::enable()
176.176 +{
176.177 + _regs[Smb_control] = _regs[Smb_control] | Smb_no_stop_empty;
176.178 +
176.179 + _regs[Smb_enable] = Smb_enable_enabled;
176.180 + while (!(_regs[Smb_enable_status] & Smb_enable_enabled));
176.181 +}
176.182 +
176.183 +// Disable the channel.
176.184 +
176.185 +void
176.186 +I2c_jz4780_channel::disable()
176.187 +{
176.188 + _regs[Smb_enable] = 0;
176.189 + while (_regs[Smb_enable_status] & Smb_enable_enabled);
176.190 +}
176.191 +
176.192 +// Set the frequency-related peripheral parameters.
176.193 +
176.194 +void
176.195 +I2c_jz4780_channel::set_frequency()
176.196 +{
176.197 + // The APB clock (PCLK) is used to drive I2C transfers. Its value must be
176.198 + // obtained from the CPM unit. It is known as SMB_CLK here and is scaled to
176.199 + // kHz in order to keep the numbers easily representable, as is the bus
176.200 + // frequency.
176.201 +
176.202 + uint32_t smb_clk = _cpm->get_pclock_frequency() / 1000;
176.203 + uint32_t i2c_clk = _frequency / 1000;
176.204 + unsigned speed = (i2c_clk <= 100) ? 1 : 2;
176.205 +
176.206 + _regs[Smb_control] = _regs[Smb_control] | (speed << Smb_speed_bit) |
176.207 + Smb_disable_slave |
176.208 + Smb_enable_restart |
176.209 + Smb_enable_master;
176.210 +
176.211 + // According to the programming manual, if the PCLK period is T{SMB_CLK}
176.212 + // then the I2C clock period is...
176.213 +
176.214 + // T{SCL} = T{SCL_high} + T{SCL_low}
176.215 +
176.216 + // Where...
176.217 +
176.218 + // T{SCL_low} = T{SMB_CLK} * (#cycles for low signal)
176.219 + // T{SCL_high} = T{SMB_CLK} * (#cycles for high signal)
176.220 +
176.221 + // Since, with minimum periods being defined...
176.222 +
176.223 + // T{SCL} >= T{min_SCL}
176.224 + // T{SCL_low} >= T{min_SCL_low}
176.225 + // T{SCL_high} >= T{min_SCL_high}
176.226 + // T{min_SCL} = T{min_SCL_low} + T{min_SCL_high}
176.227 +
176.228 + // Then the following applies...
176.229 +
176.230 + // T{SMB_CLK} * (#cycles for low signal)) >= T{min_SCL_low}
176.231 + // T{SMB_CLK} * (#cycles for high signal) >= T{min_SCL_high}
176.232 +
176.233 + // To work with different clock speeds while maintaining the low-to-high
176.234 + // ratios:
176.235 +
176.236 + // T{min_SCL_low} = T{min_SCL} * T{min_SCL_low} / T{min_SCL}
176.237 + // = T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high}))
176.238 +
176.239 + // T{min_SCL_high} = T{min_SCL} * T{min_SCL_high} / T{min_SCL}
176.240 + // = T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high}))
176.241 +
176.242 + // Constraints are given with respect to the high and low count registers.
176.243 +
176.244 + // #cycles for high signal = SMBxHCNT + 8
176.245 + // #cycles for low signal = SMBxLCNT + 1
176.246 +
176.247 + // From earlier, this yields...
176.248 +
176.249 + // T{SMB_CLK} * (SMBxLCNT + 1) >= T{min_SCL_low}
176.250 + // T{SMB_CLK} * (SMBxHCNT + 8) >= T{min_SCL_high}
176.251 +
176.252 + // Rearranging...
176.253 +
176.254 + // SMBxLCNT >= (T{min_SCL_low} / T{SMB_CLK}) - 1
176.255 + // >= T{min_SCL_low} * SMB_CLK - 1
176.256 +
176.257 + // SMBxHCNT >= (T{min_SCL_high} / T{SMB_CLK}) - 8
176.258 + // >= T{min_SCL_high} * SMB_CLK - 8
176.259 +
176.260 + // Introducing the definitions for the high and low periods...
176.261 +
176.262 + // SMBxLCNT >= T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) * SMB_CLK - 1
176.263 + // >= (T{min_SCL_low} / T{min_SCL}) * SMB_CLK / I2C_CLK - 1
176.264 +
176.265 + // SMBxHCNT >= T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) * SMB_CLK - 8
176.266 + // >= (T{min_SCL_high} / T{min_SCL}) * SMB_CLK / I2C_CLK - 8
176.267 +
176.268 + uint32_t high_reg, low_reg;
176.269 + uint32_t high_count, low_count;
176.270 + uint32_t hold_count, setup_count;
176.271 +
176.272 + // Level hold times:
176.273 +
176.274 + // Standard Fast
176.275 + // SCL low 4.7us 1.3us
176.276 + // SCL high 4.0us 0.6us +
176.277 + // SCL period 8.7us 1.9us =
176.278 +
176.279 + if (i2c_clk <= 100) // 100 kHz
176.280 + {
176.281 + low_count = (smb_clk * 47) / (i2c_clk * 87) - 1;
176.282 + high_count = (smb_clk * 40) / (i2c_clk * 87) - 8;
176.283 + low_reg = Std_low_count;
176.284 + high_reg = Std_high_count;
176.285 + }
176.286 + else
176.287 + {
176.288 + low_count = (smb_clk * 13) / (i2c_clk * 19) - 1;
176.289 + high_count = (smb_clk * 6) / (i2c_clk * 19) - 8;
176.290 + low_reg = Fast_low_count;
176.291 + high_reg = Fast_high_count;
176.292 + }
176.293 +
176.294 + // Minimum counts are 8 and 6 for low and high respectively.
176.295 +
176.296 + _regs[low_reg] = low_count < 8 ? 8 : low_count;
176.297 + _regs[high_reg] = high_count < 6 ? 6 : high_count;
176.298 +
176.299 + // Data hold and setup times:
176.300 +
176.301 + // Standard Fast
176.302 + // t{HD;DAT} 300ns 300ns
176.303 + // t{SU;DAT} 250ns 100ns
176.304 +
176.305 + // T{delay} = (SMBSDAHD + 1) * T{SMB_CLK}
176.306 + // SMBSDAHD = T{delay} / T{SMB_CLK} - 1
176.307 + // SMBSDAHD = SMB_CLK * T{delay} - 1
176.308 +
176.309 + hold_count = (smb_clk * 300) / 1000000 - 1;
176.310 +
176.311 + _regs[Smb_sda_hold_time] = (_regs[Smb_sda_hold_time] & ~Smb_hold_mask) |
176.312 + (hold_count > 0 ? Smb_hold_enable : Smb_hold_disable) |
176.313 + (hold_count < 255 ? hold_count : 255);
176.314 +
176.315 + // T{delay} = (SMBSDASU - 1) * T{SMB_CLK}
176.316 + // SMBSDASU = T{delay} / T{SMB_CLK} + 1
176.317 + // SMBSDASU = SMB_CLK * T{delay} + 1
176.318 +
176.319 + if (i2c_clk <= 100)
176.320 + setup_count = (smb_clk * 250) / 1000000 + 1;
176.321 + else
176.322 + setup_count = (smb_clk * 100) / 1000000 + 1;
176.323 +
176.324 + _regs[Smb_sda_setup_time] = (_regs[Smb_sda_setup_time] & ~Smb_setup_mask) |
176.325 + (setup_count < 255 ? setup_count : 255);
176.326 +}
176.327 +
176.328 +// Set the target address and enable transfer.
176.329 +// NOTE: Only supporting 7-bit addresses currently.
176.330 +
176.331 +void
176.332 +I2c_jz4780_channel::set_target(uint8_t address)
176.333 +{
176.334 + disable();
176.335 + set_frequency();
176.336 + _regs[Smb_target_address] = address & Smb_target_7bits;
176.337 + enable();
176.338 + init_parameters();
176.339 + queued = 0;
176.340 +}
176.341 +
176.342 +
176.343 +
176.344 +// Reset interrupt flags upon certain conditions.
176.345 +
176.346 +void
176.347 +I2c_jz4780_channel::reset_flags()
176.348 +{
176.349 + volatile uint32_t r;
176.350 +
176.351 + _regs[Int_mask] = 0;
176.352 +
176.353 + // Read from the register to clear interrupts.
176.354 +
176.355 + r = _regs[Int_combined_clear];
176.356 + (void) r;
176.357 +}
176.358 +
176.359 +// Initialise interrupt flags and queue thresholds for reading and writing.
176.360 +
176.361 +void
176.362 +I2c_jz4780_channel::init_parameters()
176.363 +{
176.364 + // Handle read queue conditions for data, write queue conditions for commands.
176.365 +
176.366 + reset_flags();
176.367 +
176.368 + _regs[Int_mask] = Int_rx_full | // read condition (reading needed)
176.369 + Int_rx_of | // abort condition
176.370 + Int_tx_empty | // write condition (writing needed)
176.371 + Int_tx_abort; // abort condition
176.372 +
176.373 + _regs[Tx_fifo_thold] = 0; // write when 0 in queue
176.374 +
176.375 + // Make sure that the stop condition does not occur automatically.
176.376 +
176.377 + _regs[Smb_control] = _regs[Smb_control] | Smb_no_stop_empty;
176.378 +}
176.379 +
176.380 +
176.381 +
176.382 +// Return whether the device is active.
176.383 +
176.384 +int
176.385 +I2c_jz4780_channel::active()
176.386 +{
176.387 + return _regs[Smb_status] & Smb_status_master_act;
176.388 +}
176.389 +
176.390 +// Return whether data is available to receive.
176.391 +
176.392 +int
176.393 +I2c_jz4780_channel::have_input()
176.394 +{
176.395 + return _regs[Smb_status] & Smb_status_rx_nempty;
176.396 +}
176.397 +
176.398 +// Return whether data is queued for sending.
176.399 +
176.400 +int
176.401 +I2c_jz4780_channel::have_output()
176.402 +{
176.403 + return !(_regs[Smb_status] & Smb_status_tx_empty);
176.404 +}
176.405 +
176.406 +// Return whether data can be queued for sending.
176.407 +
176.408 +int
176.409 +I2c_jz4780_channel::can_send()
176.410 +{
176.411 + return _regs[Smb_status] & Smb_status_tx_nfull;
176.412 +}
176.413 +
176.414 +// Return whether a receive operation has failed.
176.415 +
176.416 +int
176.417 +I2c_jz4780_channel::read_failed()
176.418 +{
176.419 + return _regs[Int_status] & Int_rx_of;
176.420 +}
176.421 +
176.422 +// Return whether a send operation has failed.
176.423 +
176.424 +int
176.425 +I2c_jz4780_channel::write_failed()
176.426 +{
176.427 + return _regs[Int_status] & Int_tx_abort;
176.428 +}
176.429 +
176.430 +
176.431 +
176.432 +// Send read commands for empty queue entries.
176.433 +
176.434 +void
176.435 +I2c_jz4780_channel::queue_reads()
176.436 +{
176.437 + unsigned remaining = _total - _reqpos;
176.438 + unsigned can_queue = Smb_fifo_limit - queued + 1;
176.439 +
176.440 + if (!remaining)
176.441 + {
176.442 + _regs[Smb_data_command] = Smb_command_read;
176.443 + return;
176.444 + }
176.445 +
176.446 + // Keep the number of reads in progress below the length of the read queue.
176.447 +
176.448 + if (!can_queue)
176.449 + {
176.450 + //printf("remaining=%d queued=%d\n", remaining, queued);
176.451 + return;
176.452 + }
176.453 +
176.454 + if (remaining < can_queue)
176.455 + can_queue = remaining;
176.456 +
176.457 + // Queue read requests for any remaining queue entries.
176.458 +
176.459 + for (unsigned i = 0; i < can_queue; i++)
176.460 + _regs[Smb_data_command] = Smb_command_read;
176.461 +
176.462 + // Track queued messages and requested positions.
176.463 +
176.464 + queued += can_queue;
176.465 + _reqpos += can_queue;
176.466 +
176.467 + if (_total == _reqpos)
176.468 + printf("Written %d read requests.\n", _reqpos);
176.469 +}
176.470 +
176.471 +// Send write commands for empty queue entries.
176.472 +
176.473 +void
176.474 +I2c_jz4780_channel::queue_writes(uint8_t buf[], unsigned *pos, unsigned total)
176.475 +{
176.476 + // Queue write requests for any remaining queue entries.
176.477 +
176.478 + while ((*pos < total) && can_send() && !write_failed())
176.479 + {
176.480 + _regs[Smb_data_command] = Smb_command_write | buf[*pos];
176.481 + (*pos)++;
176.482 + }
176.483 +}
176.484 +
176.485 +// Store read command results from the queue.
176.486 +
176.487 +void
176.488 +I2c_jz4780_channel::store_reads()
176.489 +{
176.490 + int have_read = 0;
176.491 +
176.492 + // Read any input and store it in the buffer.
176.493 +
176.494 + while (have_input() && (_pos < _total))
176.495 + {
176.496 + _buf[_pos] = _regs[Smb_data_command] & 0xff;
176.497 + queued--;
176.498 + _pos++;
176.499 +
176.500 + have_read = 1;
176.501 + }
176.502 +
176.503 + // Update the threshold to be notified of any reduced remaining amount.
176.504 +
176.505 + if (have_read)
176.506 + set_read_threshold();
176.507 +
176.508 + //printf("Read to %d, still %d queued.\n", _pos, queued);
176.509 +}
176.510 +
176.511 +// Read from the target device.
176.512 +
176.513 +void
176.514 +I2c_jz4780_channel::start_read(uint8_t buf[], unsigned total)
176.515 +{
176.516 + printf("intst=%x\n", (uint32_t) _regs[Int_status]);
176.517 +
176.518 + _buf = buf;
176.519 + _total = total;
176.520 + _pos = 0;
176.521 + _reqpos = 0;
176.522 + _fail = 0;
176.523 + _stop = 0;
176.524 +
176.525 + set_read_threshold();
176.526 +}
176.527 +
176.528 +void
176.529 +I2c_jz4780_channel::set_read_threshold()
176.530 +{
176.531 + unsigned remaining = _total - _pos;
176.532 +
176.533 + if (!remaining)
176.534 + return;
176.535 +
176.536 + if (remaining <= Smb_fifo_limit)
176.537 + _regs[Rx_fifo_thold] = remaining - 1; // read all remaining
176.538 + else
176.539 + _regs[Rx_fifo_thold] = Smb_fifo_limit - 1; // read to limit
176.540 +
176.541 + //printf("rxthold=%d\n", (uint32_t) _regs[Rx_fifo_thold] + 1);
176.542 +}
176.543 +
176.544 +void
176.545 +I2c_jz4780_channel::read()
176.546 +{
176.547 + if (read_failed() || write_failed())
176.548 + {
176.549 + printf("intst*=%x\n", (uint32_t) _regs[Int_status]);
176.550 + printf("rxfifo=%d\n", (uint32_t) _regs[Rx_fifo_count] & 0x3f);
176.551 + printf("smbabtsrc=%x\n", (uint32_t) _regs[Trans_abort_status0]);
176.552 + _fail = 1;
176.553 + return;
176.554 + }
176.555 +
176.556 + //printf("rxfifo=%d\n", (uint32_t) _regs[Rx_fifo_count]);
176.557 + //printf("intst=%x\n", (uint32_t) _regs[Int_status]);
176.558 +
176.559 + if (_pos < _total)
176.560 + {
176.561 + if (_regs[Int_status] & Int_rx_full)
176.562 + store_reads();
176.563 + if (_regs[Int_status] & Int_tx_empty)
176.564 + queue_reads();
176.565 + }
176.566 + else
176.567 + {
176.568 + stop();
176.569 + _regs[Int_mask] = 0;
176.570 + }
176.571 +}
176.572 +
176.573 +int
176.574 +I2c_jz4780_channel::read_done()
176.575 +{
176.576 + return _pos == _total;
176.577 +}
176.578 +
176.579 +unsigned
176.580 +I2c_jz4780_channel::have_read()
176.581 +{
176.582 + return _pos;
176.583 +}
176.584 +
176.585 +int
176.586 +I2c_jz4780_channel::read_incomplete()
176.587 +{
176.588 + return _fail;
176.589 +}
176.590 +
176.591 +// Write to the target device.
176.592 +
176.593 +void
176.594 +I2c_jz4780_channel::write(uint8_t buf[], unsigned total)
176.595 +{
176.596 + unsigned pos = 0;
176.597 +
176.598 + while ((pos < total) && !write_failed())
176.599 + {
176.600 + queue_writes(buf, &pos, total);
176.601 + }
176.602 +}
176.603 +
176.604 +// Explicitly stop communication.
176.605 +
176.606 +void
176.607 +I2c_jz4780_channel::stop()
176.608 +{
176.609 + if (_stop)
176.610 + return;
176.611 +
176.612 + _regs[Smb_control] = _regs[Smb_control] & ~Smb_no_stop_empty;
176.613 + _stop = 1;
176.614 + printf("Stop sent.\n");
176.615 +}
176.616 +
176.617 +
176.618 +
176.619 +// Initialise the I2C controller.
176.620 +
176.621 +I2c_jz4780_chip::I2c_jz4780_chip(l4_addr_t start, l4_addr_t end,
176.622 + Cpm_jz4780_chip *cpm,
176.623 + uint32_t frequency)
176.624 +: _start(start), _end(end), _cpm(cpm), _frequency(frequency)
176.625 +{
176.626 +}
176.627 +
176.628 +// Obtain a channel object.
176.629 +
176.630 +I2c_jz4780_channel *
176.631 +I2c_jz4780_chip::get_channel(uint8_t channel)
176.632 +{
176.633 + l4_addr_t block = _start + channel * Smb_block_offset;
176.634 +
176.635 + if (block < _end)
176.636 + {
176.637 + _cpm->start_i2c(channel);
176.638 + return new I2c_jz4780_channel(block, _cpm, _frequency);
176.639 + }
176.640 + else
176.641 + throw -L4_EINVAL;
176.642 +}
176.643 +
176.644 +
176.645 +
176.646 +// C language interface functions.
176.647 +
176.648 +void *jz4780_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, uint32_t frequency)
176.649 +{
176.650 + return (void *) new I2c_jz4780_chip(start, end, static_cast<Cpm_jz4780_chip *>(cpm), frequency);
176.651 +}
176.652 +
176.653 +void *jz4780_i2c_get_channel(void *i2c, uint8_t channel)
176.654 +{
176.655 + return static_cast<I2c_jz4780_chip *>(i2c)->get_channel(channel);
176.656 +}
176.657 +
176.658 +void jz4780_i2c_set_target(void *i2c_channel, uint8_t addr)
176.659 +{
176.660 + static_cast<I2c_jz4780_channel *>(i2c_channel)->set_target(addr);
176.661 +}
176.662 +
176.663 +void jz4780_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned total)
176.664 +{
176.665 + static_cast<I2c_jz4780_channel *>(i2c_channel)->start_read(buf, total);
176.666 +}
176.667 +
176.668 +void jz4780_i2c_read(void *i2c_channel)
176.669 +{
176.670 + static_cast<I2c_jz4780_channel *>(i2c_channel)->read();
176.671 +}
176.672 +
176.673 +int jz4780_i2c_read_done(void *i2c_channel)
176.674 +{
176.675 + return static_cast<I2c_jz4780_channel *>(i2c_channel)->read_done();
176.676 +}
176.677 +
176.678 +unsigned jz4780_i2c_have_read(void *i2c_channel)
176.679 +{
176.680 + return static_cast<I2c_jz4780_channel *>(i2c_channel)->have_read();
176.681 +}
176.682 +
176.683 +int jz4780_i2c_read_incomplete(void *i2c_channel)
176.684 +{
176.685 + return static_cast<I2c_jz4780_channel *>(i2c_channel)->read_incomplete();
176.686 +}
176.687 +
176.688 +void jz4780_i2c_write(void *i2c_channel, uint8_t buf[], unsigned total)
176.689 +{
176.690 + static_cast<I2c_jz4780_channel *>(i2c_channel)->write(buf, total);
176.691 +}
176.692 +
176.693 +void jz4780_i2c_stop(void *i2c_channel)
176.694 +{
176.695 + static_cast<I2c_jz4780_channel *>(i2c_channel)->stop();
176.696 +}
177.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
177.2 +++ b/pkg/devices/lib/keypad/Makefile Sun May 13 01:34:16 2018 +0200
177.3 @@ -0,0 +1,8 @@
177.4 +PKGDIR ?= ../..
177.5 +L4DIR ?= $(PKGDIR)/../..
177.6 +
177.7 +TARGET := include src
177.8 +
177.9 +include $(L4DIR)/mk/subdir.mk
177.10 +
177.11 +src: include
178.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
178.2 +++ b/pkg/devices/lib/keypad/include/Makefile Sun May 13 01:34:16 2018 +0200
178.3 @@ -0,0 +1,4 @@
178.4 +PKGDIR = ../../..
178.5 +L4DIR ?= $(PKGDIR)/../..
178.6 +
178.7 +include $(L4DIR)/mk/include.mk
179.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
179.2 +++ b/pkg/devices/lib/keypad/include/keypad.h Sun May 13 01:34:16 2018 +0200
179.3 @@ -0,0 +1,48 @@
179.4 +/*
179.5 + * Keypad description access.
179.6 + *
179.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
179.8 + *
179.9 + * This program is free software; you can redistribute it and/or
179.10 + * modify it under the terms of the GNU General Public License as
179.11 + * published by the Free Software Foundation; either version 2 of
179.12 + * the License, or (at your option) any later version.
179.13 + *
179.14 + * This program is distributed in the hope that it will be useful,
179.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
179.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
179.17 + * GNU General Public License for more details.
179.18 + *
179.19 + * You should have received a copy of the GNU General Public License
179.20 + * along with this program; if not, write to the Free Software
179.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
179.22 + * Boston, MA 02110-1301, USA
179.23 + */
179.24 +
179.25 +#pragma once
179.26 +
179.27 +#include <l4/sys/types.h>
179.28 +
179.29 +#ifdef __cplusplus
179.30 +
179.31 +class Keypad
179.32 +{
179.33 +public:
179.34 + virtual int columns(void) = 0;
179.35 + virtual int rows(void) = 0;
179.36 + virtual int code(int column, int row) = 0;
179.37 + static Keypad *get_keypad();
179.38 +};
179.39 +
179.40 +#endif
179.41 +
179.42 +/* C language interface. */
179.43 +
179.44 +EXTERN_C_BEGIN
179.45 +
179.46 +void *keypad_get(void);
179.47 +int keypad_columns(void *keypad);
179.48 +int keypad_rows(void *keypad);
179.49 +int keypad_code(void *keypad, int column, int row);
179.50 +
179.51 +EXTERN_C_END
180.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
180.2 +++ b/pkg/devices/lib/keypad/src/Makefile Sun May 13 01:34:16 2018 +0200
180.3 @@ -0,0 +1,6 @@
180.4 +PKGDIR ?= ../../..
180.5 +L4DIR ?= $(PKGDIR)/../..
180.6 +
180.7 +TARGET := common letux400 qi_lb60
180.8 +
180.9 +include $(L4DIR)/mk/subdir.mk
181.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
181.2 +++ b/pkg/devices/lib/keypad/src/common/Makefile Sun May 13 01:34:16 2018 +0200
181.3 @@ -0,0 +1,13 @@
181.4 +PKGDIR ?= ../../../..
181.5 +L4DIR ?= $(PKGDIR)/../..
181.6 +
181.7 +TARGET = libkeypad.o.a
181.8 +PC_FILENAME := libdrivers-keypad
181.9 +
181.10 +SRC_CC := keypad.cc
181.11 +
181.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/keypad/include
181.13 +
181.14 +REQUIRES_LIBS := l4re_c l4re_c-util
181.15 +
181.16 +include $(L4DIR)/mk/lib.mk
182.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
182.2 +++ b/pkg/devices/lib/keypad/src/common/keypad.cc Sun May 13 01:34:16 2018 +0200
182.3 @@ -0,0 +1,50 @@
182.4 +/*
182.5 + * General keypad mapping support.
182.6 + *
182.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
182.8 + *
182.9 + * This program is free software; you can redistribute it and/or
182.10 + * modify it under the terms of the GNU General Public License as
182.11 + * published by the Free Software Foundation; either version 2 of
182.12 + * the License, or (at your option) any later version.
182.13 + *
182.14 + * This program is distributed in the hope that it will be useful,
182.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
182.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
182.17 + * GNU General Public License for more details.
182.18 + *
182.19 + * You should have received a copy of the GNU General Public License
182.20 + * along with this program; if not, write to the Free Software
182.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
182.22 + * Boston, MA 02110-1301, USA
182.23 + */
182.24 +
182.25 +#include "keypad.h"
182.26 +
182.27 +/* Obtain the common instance. */
182.28 +
182.29 +void *keypad_get(void)
182.30 +{
182.31 + return reinterpret_cast<void *>(Keypad::get_keypad());
182.32 +}
182.33 +
182.34 +/* Number of keypad columns. */
182.35 +
182.36 +int keypad_columns(void *keypad)
182.37 +{
182.38 + return static_cast<Keypad *>(keypad)->columns();
182.39 +}
182.40 +
182.41 +/* Number of keypad rows, used by each value in the column array. */
182.42 +
182.43 +int keypad_rows(void *keypad)
182.44 +{
182.45 + return static_cast<Keypad *>(keypad)->rows();
182.46 +}
182.47 +
182.48 +/* Keycode accessors. */
182.49 +
182.50 +int keypad_code(void *keypad, int column, int row)
182.51 +{
182.52 + return static_cast<Keypad *>(keypad)->code(column, row);
182.53 +}
183.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
183.2 +++ b/pkg/devices/lib/keypad/src/letux400/Makefile Sun May 13 01:34:16 2018 +0200
183.3 @@ -0,0 +1,13 @@
183.4 +PKGDIR ?= ../../../..
183.5 +L4DIR ?= $(PKGDIR)/../..
183.6 +
183.7 +TARGET = libkeypad_letux400.o.a
183.8 +PC_FILENAME := libdrivers-keypad-letux400
183.9 +
183.10 +SRC_CC := keypad-letux400.cc
183.11 +
183.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/keypad/include
183.13 +
183.14 +REQUIRES_LIBS := l4re_c l4re_c-util
183.15 +
183.16 +include $(L4DIR)/mk/lib.mk
184.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
184.2 +++ b/pkg/devices/lib/keypad/src/letux400/keypad-letux400.cc Sun May 13 01:34:16 2018 +0200
184.3 @@ -0,0 +1,105 @@
184.4 +/*
184.5 + * Letux 400 key mapping.
184.6 + *
184.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
184.8 + *
184.9 + * This program is free software; you can redistribute it and/or
184.10 + * modify it under the terms of the GNU General Public License as
184.11 + * published by the Free Software Foundation; either version 2 of
184.12 + * the License, or (at your option) any later version.
184.13 + *
184.14 + * This program is distributed in the hope that it will be useful,
184.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
184.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
184.17 + * GNU General Public License for more details.
184.18 + *
184.19 + * You should have received a copy of the GNU General Public License
184.20 + * along with this program; if not, write to the Free Software
184.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
184.22 + * Boston, MA 02110-1301, USA
184.23 + */
184.24 +
184.25 +#include "keypad.h"
184.26 +#include <l4/re/event_enums.h>
184.27 +
184.28 +enum Jz4730_keypad_gpio
184.29 +{
184.30 + Jz4730_keypad_gpio_inputs_count = 8,
184.31 + Jz4730_keypad_gpio_outputs_count = 17,
184.32 +};
184.33 +
184.34 +class Keypad_letux400 : public Keypad
184.35 +{
184.36 + /* Keycode definitions. */
184.37 +
184.38 + const int keycodes[Jz4730_keypad_gpio_inputs_count][Jz4730_keypad_gpio_outputs_count] = {
184.39 +
184.40 + {L4RE_KEY_PAUSE, L4RE_KEY_Q, L4RE_KEY_W, L4RE_KEY_E, L4RE_KEY_R, L4RE_KEY_U,
184.41 + L4RE_KEY_I, L4RE_KEY_O, 0, 0, 0, L4RE_KEY_P, 0, 0, 0, 0},
184.42 +
184.43 + {0, L4RE_KEY_TAB, L4RE_KEY_CAPSLOCK, L4RE_KEY_F3, L4RE_KEY_T, L4RE_KEY_Y,
184.44 + L4RE_KEY_RIGHTBRACE, L4RE_KEY_F7, 0, L4RE_KEY_BACKSPACE, 0,
184.45 + L4RE_KEY_LEFTBRACE, L4RE_KEY_SLEEP, 0, 0, 0, L4RE_KEY_LEFTSHIFT},
184.46 +
184.47 + {0, L4RE_KEY_A, L4RE_KEY_S, L4RE_KEY_D, L4RE_KEY_F, L4RE_KEY_J, L4RE_KEY_K,
184.48 + L4RE_KEY_L, 0, 0, 0, L4RE_KEY_SEMICOLON, 0, 0, 0, L4RE_KEY_UP,
184.49 + L4RE_KEY_RIGHTSHIFT},
184.50 +
184.51 + {0, L4RE_KEY_ESC, L4RE_KEY_BACKSLASH /* left */, L4RE_KEY_F4, L4RE_KEY_G,
184.52 + L4RE_KEY_H, L4RE_KEY_F6, 0, L4RE_KEY_SPACE, 0, L4RE_KEY_LEFTALT,
184.53 + L4RE_KEY_APOSTROPHE, 0, 0, 0, L4RE_KEY_DOWN, 0},
184.54 +
184.55 + {0, L4RE_KEY_Z, L4RE_KEY_X, L4RE_KEY_C, L4RE_KEY_V, L4RE_KEY_M,
184.56 + L4RE_KEY_COMMA, L4RE_KEY_DOT, L4RE_KEY_NUMLOCK, L4RE_KEY_ENTER, 0,
184.57 + L4RE_KEY_BACKSLASH /* right */, 0, 0, 0, L4RE_KEY_LEFT, 0},
184.58 +
184.59 + {0, 0, 0, 0, L4RE_KEY_B, L4RE_KEY_N, 0, L4RE_KEY_MENU,
184.60 + 0, 0, 0, L4RE_KEY_SLASH, 0, 0, 0, L4RE_KEY_RIGHT, 0},
184.61 +
184.62 + {L4RE_KEY_LEFTCTRL, L4RE_KEY_GRAVE, 0, 0, L4RE_KEY_5, L4RE_KEY_6,
184.63 + L4RE_KEY_EQUAL, L4RE_KEY_F8, L4RE_KEY_DELETE, L4RE_KEY_F9, 0,
184.64 + L4RE_KEY_MINUS, 0, L4RE_KEY_F2, L4RE_KEY_INSERT, 0, L4RE_KEY_F1},
184.65 +
184.66 + {L4RE_KEY_F5, L4RE_KEY_1, L4RE_KEY_2, L4RE_KEY_3, L4RE_KEY_4, L4RE_KEY_7,
184.67 + L4RE_KEY_8, L4RE_KEY_9, 0, 0, L4RE_KEY_SYSRQ, L4RE_KEY_0, L4RE_KEY_F10, 0,
184.68 + 0, 0, L4RE_KEY_FN}
184.69 + };
184.70 +
184.71 +public:
184.72 +
184.73 + /* Number of keypad columns. */
184.74 +
184.75 + int columns()
184.76 + {
184.77 + return Jz4730_keypad_gpio_outputs_count;
184.78 + }
184.79 +
184.80 + /* Number of keypad rows, used by each value in the column array. */
184.81 +
184.82 + int rows()
184.83 + {
184.84 + return Jz4730_keypad_gpio_inputs_count;
184.85 + }
184.86 +
184.87 + /* Keycode accessors. */
184.88 +
184.89 + int code(int column, int row)
184.90 + {
184.91 + return keycodes[row][column];
184.92 + }
184.93 +
184.94 + /* Common instance. */
184.95 +
184.96 + static Keypad_letux400 keypad;
184.97 +};
184.98 +
184.99 +/* The actual definition. */
184.100 +
184.101 +Keypad_letux400 Keypad_letux400::keypad;
184.102 +
184.103 +/* Definition access. */
184.104 +
184.105 +Keypad *Keypad::get_keypad()
184.106 +{
184.107 + return &Keypad_letux400::keypad;
184.108 +}
185.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
185.2 +++ b/pkg/devices/lib/keypad/src/qi_lb60/Makefile Sun May 13 01:34:16 2018 +0200
185.3 @@ -0,0 +1,13 @@
185.4 +PKGDIR ?= ../../../..
185.5 +L4DIR ?= $(PKGDIR)/../..
185.6 +
185.7 +TARGET = libkeypad_qi_lb60.o.a
185.8 +PC_FILENAME := libdrivers-keypad-qi_lb60
185.9 +
185.10 +SRC_CC := keypad-qi_lb60.cc
185.11 +
185.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/keypad/include
185.13 +
185.14 +REQUIRES_LIBS := l4re_c l4re_c-util
185.15 +
185.16 +include $(L4DIR)/mk/lib.mk
186.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
186.2 +++ b/pkg/devices/lib/keypad/src/qi_lb60/keypad-qi_lb60.cc Sun May 13 01:34:16 2018 +0200
186.3 @@ -0,0 +1,99 @@
186.4 +/*
186.5 + * Ben NanoNote key mapping.
186.6 + *
186.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
186.8 + *
186.9 + * This program is free software; you can redistribute it and/or
186.10 + * modify it under the terms of the GNU General Public License as
186.11 + * published by the Free Software Foundation; either version 2 of
186.12 + * the License, or (at your option) any later version.
186.13 + *
186.14 + * This program is distributed in the hope that it will be useful,
186.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
186.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
186.17 + * GNU General Public License for more details.
186.18 + *
186.19 + * You should have received a copy of the GNU General Public License
186.20 + * along with this program; if not, write to the Free Software
186.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
186.22 + * Boston, MA 02110-1301, USA
186.23 + */
186.24 +
186.25 +#include "keypad.h"
186.26 +#include <l4/re/event_enums.h>
186.27 +
186.28 +enum Jz4740_keypad_gpio
186.29 +{
186.30 + Jz4740_keypad_gpio_inputs_count = 8,
186.31 + Jz4740_keypad_gpio_outputs_count = 8,
186.32 +};
186.33 +
186.34 +class Keypad_qi_lb60 : public Keypad
186.35 +{
186.36 + /* Keycode definitions. */
186.37 +
186.38 + const int keycodes[Jz4740_keypad_gpio_inputs_count][Jz4740_keypad_gpio_outputs_count] = {
186.39 +
186.40 + {L4RE_KEY_F1, L4RE_KEY_F2, L4RE_KEY_F3, L4RE_KEY_F4, L4RE_KEY_F5,
186.41 + L4RE_KEY_F6, L4RE_KEY_F7, 0},
186.42 +
186.43 + {L4RE_KEY_Q, L4RE_KEY_W, L4RE_KEY_E, L4RE_KEY_R, L4RE_KEY_T, L4RE_KEY_Y,
186.44 + L4RE_KEY_U, L4RE_KEY_I},
186.45 +
186.46 + {L4RE_KEY_A, L4RE_KEY_S, L4RE_KEY_D, L4RE_KEY_F, L4RE_KEY_G, L4RE_KEY_H,
186.47 + L4RE_KEY_J, L4RE_KEY_K},
186.48 +
186.49 + {L4RE_KEY_ESC, L4RE_KEY_Z, L4RE_KEY_X, L4RE_KEY_C, L4RE_KEY_V, L4RE_KEY_B,
186.50 + L4RE_KEY_N, L4RE_KEY_M},
186.51 +
186.52 + {L4RE_KEY_TAB, L4RE_KEY_CAPSLOCK /* D-Sh */, L4RE_KEY_BACKSLASH,
186.53 + L4RE_KEY_APOSTROPHE, L4RE_KEY_COMMA, L4RE_KEY_DOT, L4RE_KEY_SLASH,
186.54 + L4RE_KEY_UP},
186.55 +
186.56 + {L4RE_KEY_O, L4RE_KEY_L, L4RE_KEY_EQUAL, L4RE_KEY_RIGHTALT /* Sym */,
186.57 + L4RE_KEY_SPACE, L4RE_KEY_F13 /* Qi */, L4RE_KEY_RIGHTCTRL, L4RE_KEY_LEFT},
186.58 +
186.59 + {L4RE_KEY_F8, L4RE_KEY_P, L4RE_KEY_BACKSPACE, L4RE_KEY_ENTER,
186.60 + L4RE_KEY_VOLUMEUP, L4RE_KEY_VOLUMEDOWN, L4RE_KEY_DOWN, L4RE_KEY_RIGHT},
186.61 +
186.62 + {L4RE_KEY_LEFTSHIFT, L4RE_KEY_LEFTALT, L4RE_KEY_FN, 0, 0, 0, 0, 0}
186.63 + };
186.64 +
186.65 +public:
186.66 +
186.67 + /* Number of keypad columns. */
186.68 +
186.69 + int columns()
186.70 + {
186.71 + return Jz4740_keypad_gpio_outputs_count;
186.72 + }
186.73 +
186.74 + /* Number of keypad rows, used by each value in the column array. */
186.75 +
186.76 + int rows()
186.77 + {
186.78 + return Jz4740_keypad_gpio_inputs_count;
186.79 + }
186.80 +
186.81 + /* Keycode accessors. */
186.82 +
186.83 + int code(int column, int row)
186.84 + {
186.85 + return keycodes[row][column];
186.86 + }
186.87 +
186.88 + /* Common instance. */
186.89 +
186.90 + static Keypad_qi_lb60 keypad;
186.91 +};
186.92 +
186.93 +/* The actual definition. */
186.94 +
186.95 +Keypad_qi_lb60 Keypad_qi_lb60::keypad;
186.96 +
186.97 +/* Definition access. */
186.98 +
186.99 +Keypad *Keypad::get_keypad()
186.100 +{
186.101 + return &Keypad_qi_lb60::keypad;
186.102 +}
187.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
187.2 +++ b/pkg/devices/lib/lcd/Makefile Sun May 13 01:34:16 2018 +0200
187.3 @@ -0,0 +1,8 @@
187.4 +PKGDIR ?= ../..
187.5 +L4DIR ?= $(PKGDIR)/../..
187.6 +
187.7 +TARGET := include src
187.8 +
187.9 +include $(L4DIR)/mk/subdir.mk
187.10 +
187.11 +src: include
188.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
188.2 +++ b/pkg/devices/lib/lcd/include/Makefile Sun May 13 01:34:16 2018 +0200
188.3 @@ -0,0 +1,6 @@
188.4 +PKGDIR = ../../..
188.5 +L4DIR ?= $(PKGDIR)/../..
188.6 +
188.7 +PC_FILENAME := libdrivers-lcd-headers
188.8 +
188.9 +include $(L4DIR)/mk/include.mk
189.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
189.2 +++ b/pkg/devices/lib/lcd/include/lcd-jz4740-config.h Sun May 13 01:34:16 2018 +0200
189.3 @@ -0,0 +1,85 @@
189.4 +/*
189.5 + * LCD configuration value definitions for the JZ4740 and related SoCs.
189.6 + *
189.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
189.8 + *
189.9 + * This program is free software; you can redistribute it and/or
189.10 + * modify it under the terms of the GNU General Public License as
189.11 + * published by the Free Software Foundation; either version 2 of
189.12 + * the License, or (at your option) any later version.
189.13 + *
189.14 + * This program is distributed in the hope that it will be useful,
189.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
189.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
189.17 + * GNU General Public License for more details.
189.18 + *
189.19 + * You should have received a copy of the GNU General Public License
189.20 + * along with this program; if not, write to the Free Software
189.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
189.22 + * Boston, MA 02110-1301, USA
189.23 + */
189.24 +
189.25 +#pragma once
189.26 +
189.27 +enum Jz4740_lcd_config_bits : unsigned
189.28 +{
189.29 + Jz4740_lcd_config_lcd_pin = 31, /* LCDPIN */
189.30 + Jz4740_lcd_config_tv_pal_halfline = 30, /* JZ4780: TVEPEH */
189.31 + Jz4740_lcd_config_desc_8_word = 28, /* JZ4780: NEWDES */
189.32 + Jz4740_lcd_config_tv_enable = 26, /* JZ4780: TVEN */
189.33 + Jz4740_lcd_config_underrun_recover = 25, /* JZ4780: RECOVER */
189.34 + Jz4740_lcd_config_ps_disable = 23, /* PSM */
189.35 + Jz4740_lcd_config_cls_disable = 22, /* CLSM */
189.36 + Jz4740_lcd_config_spl_disable = 21, /* SPLM */
189.37 + Jz4740_lcd_config_rev_disable = 20, /* REVM */
189.38 + Jz4740_lcd_config_hsync_mod_disable = 19, /* HSYNM (hsync polarity choice) */
189.39 + Jz4740_lcd_config_pclock_mod_disable = 18, /* PCLKM (dot/pixel clock polarity choice) */
189.40 + Jz4740_lcd_config_data_inverse = 17, /* INVDAT (inverse output data) */
189.41 + Jz4740_lcd_config_sync_input = 16, /* SYNDIR (hsync/vsync direction) */
189.42 + Jz4740_lcd_config_ps_reset = 15, /* PSP */
189.43 + Jz4740_lcd_config_cls_reset = 14, /* CLSP */
189.44 + Jz4740_lcd_config_spl_reset = 13, /* SPLP */
189.45 + Jz4740_lcd_config_rev_reset = 12, /* REVP */
189.46 + Jz4740_lcd_config_hsync_active_low = 11, /* HSP (hsync polarity) */
189.47 + Jz4740_lcd_config_pclock_fall_edge = 10, /* PCP (dot/pixel clock polarity) */
189.48 + Jz4740_lcd_config_de_active_low = 9, /* DEP (data enable polarity) */
189.49 + Jz4740_lcd_config_vsync_fall_edge = 8, /* VSP (vsync polarity) */
189.50 + Jz4740_lcd_config_bpp = 6, /* 16/18/24bpp selection for generic TFT */
189.51 + Jz4740_lcd_config_stn_pins = 4, /* PDW (STN pins utilisation) */
189.52 + Jz4740_lcd_config_mode = 0,
189.53 +};
189.54 +
189.55 +enum Jz4740_lcd_bpp_values : unsigned
189.56 +{
189.57 + Jz4740_lcd_bpp_16 = 0,
189.58 + Jz4740_lcd_bpp_24 = 1, /* JZ4780 */
189.59 + Jz4740_lcd_bpp_18 = 2,
189.60 +};
189.61 +
189.62 +enum Jz4740_lcd_modes : unsigned
189.63 +{
189.64 + Jz4740_lcd_mode_tft_generic = 0, /* parallel 16/18/24-bit panel */
189.65 + Jz4740_lcd_mode_tft_sharp = 1,
189.66 + Jz4740_lcd_mode_tft_casio = 2,
189.67 + Jz4740_lcd_mode_tft_samsung = 3,
189.68 + Jz4740_lcd_mode_ccir656_nonint = 4, /* non-interlaced (TV out) */
189.69 + Jz4740_lcd_mode_ccir656_int = 6, /* interlaced (TV out) */
189.70 + Jz4740_lcd_mode_stn_single_colour = 8, /* single == one panel */
189.71 + Jz4740_lcd_mode_stn_single_mono = 9,
189.72 + Jz4740_lcd_mode_stn_dual_colour = 10, /* dual == two panels */
189.73 + Jz4740_lcd_mode_stn_dual_mono = 11,
189.74 + Jz4740_lcd_mode_tft_serial = 12, /* serial 8-bit panel */
189.75 + Jz4740_lcd_mode_lcm = 13, /* JZ4780 */
189.76 +};
189.77 +
189.78 +enum Jz4740_lcd_config_values : unsigned
189.79 +{
189.80 + Jz4740_lcd_de_positive = 0 << Jz4740_lcd_config_de_active_low,
189.81 + Jz4740_lcd_de_negative = 1 << Jz4740_lcd_config_de_active_low,
189.82 + Jz4740_lcd_pclock_positive = 0 << Jz4740_lcd_config_pclock_fall_edge,
189.83 + Jz4740_lcd_pclock_negative = 1 << Jz4740_lcd_config_pclock_fall_edge,
189.84 + Jz4740_lcd_hsync_positive = 0 << Jz4740_lcd_config_hsync_active_low,
189.85 + Jz4740_lcd_hsync_negative = 1 << Jz4740_lcd_config_hsync_active_low,
189.86 + Jz4740_lcd_vsync_positive = 0 << Jz4740_lcd_config_vsync_fall_edge,
189.87 + Jz4740_lcd_vsync_negative = 1 << Jz4740_lcd_config_vsync_fall_edge,
189.88 +};
190.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
190.2 +++ b/pkg/devices/lib/lcd/include/lcd-jz4740-panel.h Sun May 13 01:34:16 2018 +0200
190.3 @@ -0,0 +1,53 @@
190.4 +/*
190.5 + * LCD panel definitions for the JZ4740 and related SoCs.
190.6 + *
190.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
190.8 + *
190.9 + * This program is free software; you can redistribute it and/or
190.10 + * modify it under the terms of the GNU General Public License as
190.11 + * published by the Free Software Foundation; either version 2 of
190.12 + * the License, or (at your option) any later version.
190.13 + *
190.14 + * This program is distributed in the hope that it will be useful,
190.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
190.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
190.17 + * GNU General Public License for more details.
190.18 + *
190.19 + * You should have received a copy of the GNU General Public License
190.20 + * along with this program; if not, write to the Free Software
190.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
190.22 + * Boston, MA 02110-1301, USA
190.23 + */
190.24 +
190.25 +#pragma once
190.26 +
190.27 +#include <stdint.h>
190.28 +
190.29 +/* Panel configuration details. */
190.30 +
190.31 +struct Jz4740_lcd_panel
190.32 +{
190.33 + uint32_t config; /* LCD configuration */
190.34 +
190.35 + /* Display dimensions in pixels. */
190.36 +
190.37 + uint32_t width, height;
190.38 + uint32_t bpp; /* bits per pixel */
190.39 +
190.40 + /* Display timing information. */
190.41 +
190.42 + uint32_t frame_rate; /* frame clock frequency (Hz) */
190.43 +
190.44 + /* Horizontal and vertical sync widths. */
190.45 +
190.46 + uint32_t hsync; /* in pixel clock periods */
190.47 + uint32_t vsync; /* in line periods */
190.48 +
190.49 + /* Inactive line region sizes before/after line data (in pixel clock periods). */
190.50 +
190.51 + uint32_t line_start, line_end; /* similar to horizontal back porch, front porch */
190.52 +
190.53 + /* Inactive frame region sizes before/after frame data (in line periods). */
190.54 +
190.55 + uint32_t frame_start, frame_end; /* vertical back porch, front porch */
190.56 +};
191.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
191.2 +++ b/pkg/devices/lib/lcd/include/lcd-jz4740.h Sun May 13 01:34:16 2018 +0200
191.3 @@ -0,0 +1,155 @@
191.4 +/*
191.5 + * LCD peripheral support for the JZ4740 and related SoCs.
191.6 + *
191.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
191.8 + *
191.9 + * This program is free software; you can redistribute it and/or
191.10 + * modify it under the terms of the GNU General Public License as
191.11 + * published by the Free Software Foundation; either version 2 of
191.12 + * the License, or (at your option) any later version.
191.13 + *
191.14 + * This program is distributed in the hope that it will be useful,
191.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
191.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
191.17 + * GNU General Public License for more details.
191.18 + *
191.19 + * You should have received a copy of the GNU General Public License
191.20 + * along with this program; if not, write to the Free Software
191.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
191.22 + * Boston, MA 02110-1301, USA
191.23 + */
191.24 +
191.25 +#pragma once
191.26 +
191.27 +#include "lcd.h"
191.28 +#include "lcd-jz4740-panel.h"
191.29 +
191.30 +#include <l4/sys/types.h>
191.31 +
191.32 +#include <stdint.h>
191.33 +
191.34 +/* Descriptor referenced by the DMA mechanism. */
191.35 +
191.36 +struct Jz4740_lcd_descriptor
191.37 +{
191.38 + struct Jz4740_lcd_descriptor *next; /* FDADR: frame descriptor address */
191.39 + uint32_t source; /* FSADR: frame source address */
191.40 + uint32_t identifier; /* FIDR: frame identifier */
191.41 + uint32_t command; /* CMD: command */
191.42 +};
191.43 +
191.44 +
191.45 +
191.46 +/* C++ language interface. */
191.47 +
191.48 +#ifdef __cplusplus
191.49 +
191.50 +#include <l4/devices/hw_mmio_register_block.h>
191.51 +
191.52 +/* General JZ4740 LCD controller support. */
191.53 +
191.54 +class Lcd_jz4740_chip : public Lcd_chip
191.55 +{
191.56 +private:
191.57 + Hw::Register_block<32> _regs;
191.58 + Jz4740_lcd_panel *_panel;
191.59 + int _burst_size;
191.60 +
191.61 + /* Control register value calculation. */
191.62 +
191.63 + uint32_t _control_bpp();
191.64 + uint32_t _control_panel();
191.65 + uint32_t _control_stn_frc();
191.66 + uint32_t _control_transfer();
191.67 +
191.68 + /* Panel mode access. */
191.69 +
191.70 + uint32_t _mode();
191.71 +
191.72 + /* Panel initialisation. */
191.73 +
191.74 + void _init_stn();
191.75 + void _init_tft();
191.76 + void _init_panel();
191.77 +
191.78 + /* Descriptor initialisation. */
191.79 +
191.80 + void _set_descriptor(struct Jz4740_lcd_descriptor &desc, l4_addr_t source,
191.81 + l4_size_t size, struct Jz4740_lcd_descriptor *next,
191.82 + uint32_t flags = 0);
191.83 +
191.84 +public:
191.85 + Lcd_jz4740_chip(l4_addr_t addr, Jz4740_lcd_panel *panel);
191.86 +
191.87 + struct Jz4740_lcd_panel *get_panel();
191.88 +
191.89 + /* Peripheral control. */
191.90 +
191.91 + void disable();
191.92 + void disable_quick();
191.93 + void enable();
191.94 +
191.95 + /* Peripheral properties. */
191.96 +
191.97 + int get_pixel_clock();
191.98 +
191.99 + /* Panel properties. */
191.100 +
191.101 + int get_panels();
191.102 + int have_stn_panel();
191.103 + int have_colour_stn();
191.104 + int have_serial_tft();
191.105 +
191.106 + /* Memory properties. */
191.107 +
191.108 + l4_size_t get_line_size();
191.109 + l4_size_t get_screen_size();
191.110 + l4_size_t get_aligned_size();
191.111 + l4_size_t get_palette_size();
191.112 + l4_size_t get_aligned_palette_size();
191.113 +
191.114 + /* Memory properties for allocation purposes. */
191.115 +
191.116 + l4_size_t get_total_size();
191.117 + l4_size_t get_descriptors_size();
191.118 +
191.119 + /* Memory region access. */
191.120 +
191.121 + l4_addr_t get_palette(l4_addr_t screen);
191.122 + l4_addr_t get_framebuffer(int panel, l4_addr_t screen);
191.123 +
191.124 + /* Convenience methods. */
191.125 +
191.126 + void init_palette(l4_addr_t palette);
191.127 +
191.128 + /* Configuration. */
191.129 +
191.130 + void config(struct Jz4740_lcd_descriptor *desc_vaddr,
191.131 + struct Jz4740_lcd_descriptor *desc_paddr,
191.132 + l4_addr_t fb_paddr);
191.133 +};
191.134 +
191.135 +#endif
191.136 +
191.137 +
191.138 +
191.139 +/* C language interface. */
191.140 +
191.141 +EXTERN_C_BEGIN
191.142 +
191.143 +void *jz4740_lcd_init(l4_addr_t lcd_base, struct Jz4740_lcd_panel *panel);
191.144 +
191.145 +void jz4740_lcd_config(void *lcd, struct Jz4740_lcd_descriptor *desc_vaddr,
191.146 + struct Jz4740_lcd_descriptor *desc_paddr,
191.147 + l4_addr_t fb_paddr);
191.148 +
191.149 +void jz4740_lcd_disable(void *lcd);
191.150 +void jz4740_lcd_disable_quick(void *lcd);
191.151 +void jz4740_lcd_enable(void *lcd);
191.152 +
191.153 +l4_addr_t jz4740_lcd_get_palette(void *lcd, l4_addr_t base);
191.154 +int jz4740_lcd_get_pixel_clock(void *lcd);
191.155 +
191.156 +void jz4740_lcd_init_palette(void *lcd, l4_addr_t palette);
191.157 +
191.158 +EXTERN_C_END
192.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
192.2 +++ b/pkg/devices/lib/lcd/include/lcd.h Sun May 13 01:34:16 2018 +0200
192.3 @@ -0,0 +1,30 @@
192.4 +/*
192.5 + * LCD peripheral support.
192.6 + *
192.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
192.8 + *
192.9 + * This program is free software; you can redistribute it and/or
192.10 + * modify it under the terms of the GNU General Public License as
192.11 + * published by the Free Software Foundation; either version 2 of
192.12 + * the License, or (at your option) any later version.
192.13 + *
192.14 + * This program is distributed in the hope that it will be useful,
192.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
192.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
192.17 + * GNU General Public License for more details.
192.18 + *
192.19 + * You should have received a copy of the GNU General Public License
192.20 + * along with this program; if not, write to the Free Software
192.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
192.22 + * Boston, MA 02110-1301, USA
192.23 + */
192.24 +
192.25 +#pragma once
192.26 +
192.27 +#ifdef __cplusplus
192.28 +
192.29 +class Lcd_chip
192.30 +{
192.31 +};
192.32 +
192.33 +#endif
193.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
193.2 +++ b/pkg/devices/lib/lcd/src/Makefile Sun May 13 01:34:16 2018 +0200
193.3 @@ -0,0 +1,6 @@
193.4 +PKGDIR ?= ../../..
193.5 +L4DIR ?= $(PKGDIR)/../..
193.6 +
193.7 +TARGET := jz4740
193.8 +
193.9 +include $(L4DIR)/mk/subdir.mk
194.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
194.2 +++ b/pkg/devices/lib/lcd/src/jz4740/Makefile Sun May 13 01:34:16 2018 +0200
194.3 @@ -0,0 +1,13 @@
194.4 +PKGDIR ?= ../../../..
194.5 +L4DIR ?= $(PKGDIR)/../..
194.6 +
194.7 +TARGET = liblcd_jz4740.o.a
194.8 +PC_FILENAME := libdrivers-lcd-jz4740
194.9 +
194.10 +SRC_CC := lcd-jz4740.cc
194.11 +
194.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/lcd/include
194.13 +
194.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common
194.15 +
194.16 +include $(L4DIR)/mk/lib.mk
195.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
195.2 +++ b/pkg/devices/lib/lcd/src/jz4740/lcd-jz4740.cc Sun May 13 01:34:16 2018 +0200
195.3 @@ -0,0 +1,749 @@
195.4 +/*
195.5 + * LCD peripheral support for the JZ4740 and related SoCs.
195.6 + *
195.7 + * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
195.8 + * Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
195.9 + *
195.10 + * This program is free software; you can redistribute it and/or
195.11 + * modify it under the terms of the GNU General Public License as
195.12 + * published by the Free Software Foundation; either version 2 of
195.13 + * the License, or (at your option) any later version.
195.14 + *
195.15 + * This program is distributed in the hope that it will be useful,
195.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
195.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
195.18 + * GNU General Public License for more details.
195.19 + *
195.20 + * You should have received a copy of the GNU General Public License
195.21 + * along with this program; if not, write to the Free Software
195.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
195.23 + * Boston, MA 02110-1301, USA
195.24 + */
195.25 +
195.26 +#include <l4/devices/hw_mmio_register_block.h>
195.27 +#include <l4/sys/cache.h>
195.28 +#include <l4/sys/types.h>
195.29 +
195.30 +#include "lcd-jz4740.h"
195.31 +#include "lcd-jz4740-config.h"
195.32 +
195.33 +#include <stdint.h>
195.34 +
195.35 +enum Regs : unsigned
195.36 +{
195.37 + Lcd_config = 0x000, // LCD_CFG
195.38 + Lcd_vsync = 0x004, // LCD_VSYNC
195.39 + Lcd_hsync = 0x008, // LCD_HSYNC
195.40 + Vertical_area = 0x00c, // LCD_VAT
195.41 + Display_hlimits = 0x010, // LCD_DAH
195.42 + Display_vlimits = 0x014, // LCD_DAV
195.43 + Lcd_ps = 0x018, // LCD_PS
195.44 + Lcd_cls = 0x01c, // LCD_CLS
195.45 + Lcd_spl = 0x020, // LCD_SPL
195.46 + Lcd_rev = 0x024, // LCD_REV
195.47 + Lcd_control = 0x030, // LCD_CTRL
195.48 + Lcd_status = 0x034, // LCD_STATE
195.49 + Lcd_irq_id = 0x038, // LCD_IID
195.50 + Desc_address_0 = 0x040, // LCD_DA0
195.51 + Source_address_0 = 0x044, // LCD_SA0
195.52 + Frame_id_0 = 0x048, // LCD_FID0
195.53 + Command_0 = 0x04c, // LCD_CMD0
195.54 + Desc_address_1 = 0x050, // LCD_DA1
195.55 + Source_address_1 = 0x054, // LCD_SA1
195.56 + Frame_id_1 = 0x058, // LCD_FID1
195.57 + Command_1 = 0x05c, // LCD_CMD1
195.58 +};
195.59 +
195.60 +// Lcd_config descriptions.
195.61 +
195.62 +enum Config_values : unsigned
195.63 +{
195.64 + Config_stn_pins_mask = 0x3,
195.65 + Config_mode_mask = 0xf,
195.66 +};
195.67 +
195.68 +// Field positions for registers employing two values, with the first typically
195.69 +// being the start value and the second being an end value.
195.70 +
195.71 +enum Value_pair_bits : unsigned
195.72 +{
195.73 + Value_first = 16,
195.74 + Value_second = 0,
195.75 +};
195.76 +
195.77 +// Vertical_area bits.
195.78 +
195.79 +enum Vertical_area_values : unsigned
195.80 +{
195.81 + Vertical_area_horizontal_size = Value_first, // sum of display and blank regions (dot/pixel clock periods)
195.82 + Vertical_area_vertical_size = Value_second, // sum of display and blank regions (line periods)
195.83 +};
195.84 +
195.85 +// Lcd_control descriptions.
195.86 +
195.87 +enum Control_bits : unsigned
195.88 +{
195.89 + Control_burst_length = 28, // BST (burst length selection)
195.90 + Control_rgb_mode = 27, // RGB (RGB mode)
195.91 + Control_out_underrun = 26, // OFUP (output FIFO underrun protection)
195.92 + Control_frc_algorithm = 24, // FRC (STN FRC algorithm selection)
195.93 + Control_palette_delay = 16, // PDD (load palette delay counter)
195.94 + Control_frame_end_irq_mask = 13, // EOFM (end of frame interrupt mask)
195.95 + Control_frame_start_irq_mask = 12, // SOFM (start of frame interrupt mask)
195.96 + Control_out_underrun_irq_mask = 11, // OFUM (output FIFO underrun interrupt mask)
195.97 + Control_in0_underrun_irq_mask = 10, // IFUM0 (input FIFO 0 underrun interrupt mask)
195.98 + Control_in1_underrun_irq_mask = 9, // IFUM1 (input FIFO 1 underrun interrupt mask)
195.99 + Control_disabled_irq_mask = 8, // LDDM (LCD disable done interrupt mask)
195.100 + Control_quick_disabled_irq_mask = 7, // QDM (LCD quick disable done interrupt mask)
195.101 + Control_endian_select = 6, // BEDN (endian selection)
195.102 + Control_bit_order = 5, // PEDN (bit order in bytes)
195.103 + Control_disable = 4, // DIS (disable controller)
195.104 + Control_enable = 3, // ENA (enable controller)
195.105 + Control_bpp = 0, // BPP (bits per pixel)
195.106 +};
195.107 +
195.108 +enum Burst_length_values : unsigned
195.109 +{
195.110 + Burst_length_4 = 0, // 4 word
195.111 + Burst_length_8 = 1, // 8 word
195.112 + Burst_length_16 = 2, // 16 word
195.113 +
195.114 + // JZ4780 extensions.
195.115 +
195.116 + Burst_length_32 = 3, // 32 word
195.117 + Burst_length_64 = 4, // 64 word
195.118 + Burst_length_mask = 0x7,
195.119 +};
195.120 +
195.121 +enum Rgb_mode_values : unsigned
195.122 +{
195.123 + Rgb_mode_565 = 0,
195.124 + Rgb_mode_555 = 1,
195.125 + Rgb_mode_mask = 0x1,
195.126 +};
195.127 +
195.128 +enum Frc_algorithm_values : unsigned
195.129 +{
195.130 + Frc_greyscales_16 = 0,
195.131 + Frc_greyscales_4 = 1,
195.132 + Frc_greyscales_2 = 2,
195.133 + Frc_greyscales_mask = 0x3,
195.134 +};
195.135 +
195.136 +enum Control_bpp_values : unsigned
195.137 +{
195.138 + Control_bpp_1bpp = 0,
195.139 + Control_bpp_2bpp = 1,
195.140 + Control_bpp_4bpp = 2,
195.141 + Control_bpp_8bpp = 3,
195.142 + Control_bpp_15bpp = 4,
195.143 + Control_bpp_16bpp = 4,
195.144 + Control_bpp_18bpp = 5,
195.145 + Control_bpp_24bpp = 5,
195.146 + Control_bpp_24bpp_comp = 6,
195.147 + Control_bpp_30bpp = 7,
195.148 + Control_bpp_32bpp = 7,
195.149 + Control_bpp_mask = 0x7,
195.150 +};
195.151 +
195.152 +// Command descriptions.
195.153 +
195.154 +enum Command_bits : unsigned
195.155 +{
195.156 + Command_frame_start_irq = 31, // SOFINT (start of frame interrupt)
195.157 + Command_frame_end_irq = 30, // EOFINT (end of frame interrupt)
195.158 + Command_lcm_command = 29, // JZ4780: CMD (LCM command/data via DMA0)
195.159 + Command_palette_buffer = 28, // PAL (descriptor references palette, not display data)
195.160 + Command_frame_compressed = 27, // JZ4780: COMPEN (16/24bpp compression enabled)
195.161 + Command_frame_enable = 26, // JZ4780: FRM_EN
195.162 + Command_field_even = 25, // JZ4780: FIELD_SEL (interlace even field)
195.163 + Command_16x16_block = 24, // JZ4780: 16x16BLOCK (fetch data by 16x16 block)
195.164 + Command_buffer_length = 0, // LEN
195.165 +};
195.166 +
195.167 +enum Command_values : unsigned
195.168 +{
195.169 + Command_buffer_length_mask = 0x00ffffff,
195.170 +};
195.171 +
195.172 +
195.173 +
195.174 +// Utility functions.
195.175 +
195.176 +// Round values up according to the resolution.
195.177 +
195.178 +static uint32_t align(uint32_t value, uint32_t resolution)
195.179 +{
195.180 + return (value + (resolution - 1)) & ~(resolution - 1);
195.181 +}
195.182 +
195.183 +// Value pair encoding.
195.184 +
195.185 +static uint32_t encode_pair(uint32_t start, uint32_t end)
195.186 +{
195.187 + return (start << Value_first) | (end << Value_second);
195.188 +}
195.189 +
195.190 +// RGB conversions.
195.191 +
195.192 +static uint16_t rgb8_to_rgb16(uint8_t rgb)
195.193 +{
195.194 + return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10);
195.195 +}
195.196 +
195.197 +static uint16_t rgb4_to_rgb16(uint8_t rgb)
195.198 +{
195.199 + return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f);
195.200 +}
195.201 +
195.202 +
195.203 +
195.204 +
195.205 +// If implemented as a Hw::Device, various properties would be
195.206 +// initialised in the constructor and obtained from the device tree
195.207 +// definitions.
195.208 +
195.209 +Lcd_jz4740_chip::Lcd_jz4740_chip(l4_addr_t addr, Jz4740_lcd_panel *panel)
195.210 +: _panel(panel)
195.211 +{
195.212 + _regs = new Hw::Mmio_register_block<32>(addr);
195.213 + _burst_size = 16; // 16-word burst size
195.214 +
195.215 + // add_cid("lcd");
195.216 + // add_cid("lcd-jz4740");
195.217 +}
195.218 +
195.219 +struct Jz4740_lcd_panel *
195.220 +Lcd_jz4740_chip::get_panel()
195.221 +{
195.222 + return _panel;
195.223 +}
195.224 +
195.225 +void
195.226 +Lcd_jz4740_chip::disable()
195.227 +{
195.228 + // Set the disable bit for normal shutdown.
195.229 +
195.230 + _regs[Lcd_control] = _regs[Lcd_control] | (1 << Control_disable);
195.231 +}
195.232 +
195.233 +void
195.234 +Lcd_jz4740_chip::disable_quick()
195.235 +{
195.236 + // Clear the enable bit for quick shutdown.
195.237 +
195.238 + _regs[Lcd_control] = _regs[Lcd_control] & ~(1 << Control_enable);
195.239 +}
195.240 +
195.241 +void
195.242 +Lcd_jz4740_chip::enable()
195.243 +{
195.244 + // Clear the disable bit and set the enable bit.
195.245 +
195.246 + _regs[Lcd_control] = (_regs[Lcd_control] & ~(1 << Control_disable)) | (1 << Control_enable);
195.247 +}
195.248 +
195.249 +// Calculate and return the pixel clock frequency.
195.250 +
195.251 +int
195.252 +Lcd_jz4740_chip::get_pixel_clock()
195.253 +{
195.254 + int pclk, multiplier;
195.255 +
195.256 + // Serial mode: 3 pixel clock cycles per pixel (one per channel).
195.257 + // Parallel mode: 1 pixel clock cycle per pixel.
195.258 +
195.259 + multiplier = have_serial_tft() ? 3 : 1;
195.260 +
195.261 + // Derive pixel clock rate from frame rate.
195.262 + // This multiplies the number of pixel periods in a line by the number of
195.263 + // lines in a frame, thus obtaining the number of such periods in a frame.
195.264 + // Multiplying this result with the frame rate yields the pixel frequency.
195.265 +
195.266 + pclk = _panel->frame_rate *
195.267 + (_panel->width * multiplier +
195.268 + _panel->hsync + _panel->line_start + _panel->line_end) *
195.269 + (_panel->height +
195.270 + _panel->vsync + _panel->frame_start + _panel->frame_end);
195.271 +
195.272 + // STN panel adjustments.
195.273 +
195.274 + if (have_stn_panel())
195.275 + {
195.276 + // Colour STN panels apparently need to be driven at three times the rate.
195.277 +
195.278 + if (have_colour_stn()) pclk = (pclk * 3);
195.279 +
195.280 + // Reduce the rate according to the width of the STN connection.
195.281 + // Since the pins setting employs log2(pins), a shift by this value is
195.282 + // equivalent to a division by the number of pins.
195.283 +
195.284 + pclk = pclk >> ((_panel->config & Config_stn_pins_mask) >> Jz4740_lcd_config_stn_pins);
195.285 +
195.286 + // Divide the rate by the number of panels.
195.287 +
195.288 + pclk /= get_panels();
195.289 + }
195.290 +
195.291 + return pclk;
195.292 +}
195.293 +
195.294 +
195.295 +
195.296 +// Return the panel mode.
195.297 +
195.298 +uint32_t
195.299 +Lcd_jz4740_chip::_mode()
195.300 +{
195.301 + return _panel->config & Config_mode_mask;
195.302 +}
195.303 +
195.304 +// Return the number of panels available.
195.305 +
195.306 +int
195.307 +Lcd_jz4740_chip::get_panels()
195.308 +{
195.309 + uint32_t mode = _mode();
195.310 +
195.311 + return (mode == Jz4740_lcd_mode_stn_dual_colour) ||
195.312 + (mode == Jz4740_lcd_mode_stn_dual_mono) ? 2 : 1;
195.313 +}
195.314 +
195.315 +// Return whether the panel is STN.
195.316 +
195.317 +int
195.318 +Lcd_jz4740_chip::have_stn_panel()
195.319 +{
195.320 + uint32_t mode = _mode();
195.321 +
195.322 + return ((mode == Jz4740_lcd_mode_stn_single_colour) ||
195.323 + (mode == Jz4740_lcd_mode_stn_dual_colour) ||
195.324 + (mode == Jz4740_lcd_mode_stn_single_mono) ||
195.325 + (mode == Jz4740_lcd_mode_stn_dual_mono));
195.326 +}
195.327 +
195.328 +// Return whether the panel is colour STN.
195.329 +
195.330 +int
195.331 +Lcd_jz4740_chip::have_colour_stn()
195.332 +{
195.333 + uint32_t mode = _mode();
195.334 +
195.335 + return ((mode == Jz4740_lcd_mode_stn_single_colour) ||
195.336 + (mode == Jz4740_lcd_mode_stn_dual_colour));
195.337 +}
195.338 +
195.339 +// Return whether the panel is colour STN.
195.340 +
195.341 +int
195.342 +Lcd_jz4740_chip::have_serial_tft()
195.343 +{
195.344 + return _mode() == Jz4740_lcd_mode_tft_serial;
195.345 +}
195.346 +
195.347 +
195.348 +
195.349 +// Return the line memory size.
195.350 +
195.351 +l4_size_t
195.352 +Lcd_jz4740_chip::get_line_size()
195.353 +{
195.354 + // Lines must be aligned to a word boundary.
195.355 +
195.356 + return align((_panel->width * _panel->bpp) / 8, sizeof(uint32_t));
195.357 +}
195.358 +
195.359 +// Return the screen memory size.
195.360 +
195.361 +l4_size_t
195.362 +Lcd_jz4740_chip::get_screen_size()
195.363 +{
195.364 + return get_line_size() * _panel->height;
195.365 +}
195.366 +
195.367 +// Return the aligned size for the DMA transfer.
195.368 +
195.369 +l4_size_t
195.370 +Lcd_jz4740_chip::get_aligned_size()
195.371 +{
195.372 + return align(get_screen_size(), _burst_size * sizeof(uint32_t));
195.373 +}
195.374 +
195.375 +// Return the size of the palette.
195.376 +
195.377 +l4_size_t
195.378 +Lcd_jz4740_chip::get_palette_size()
195.379 +{
195.380 + // No palette for modes with more than eight bits per pixel.
195.381 +
195.382 + if (_panel->bpp > 8) return 0;
195.383 +
195.384 + // Get the size of a collection of two-byte entries, one per colour.
195.385 +
195.386 + return (1 << (_panel->bpp)) * sizeof(uint16_t);
195.387 +}
195.388 +
195.389 +// Return the aligned size of the palette for the DMA transfer.
195.390 +
195.391 +l4_size_t
195.392 +Lcd_jz4740_chip::get_aligned_palette_size()
195.393 +{
195.394 + return align(get_palette_size(), _burst_size * sizeof(uint32_t));
195.395 +}
195.396 +
195.397 +// Return the total memory requirements of the framebuffers and palette.
195.398 +
195.399 +l4_size_t
195.400 +Lcd_jz4740_chip::get_total_size()
195.401 +{
195.402 + return get_aligned_size() * get_panels() + get_aligned_palette_size();
195.403 +}
195.404 +
195.405 +// Return the total memory requirements of any DMA descriptors.
195.406 +
195.407 +l4_size_t
195.408 +Lcd_jz4740_chip::get_descriptors_size()
195.409 +{
195.410 + return 3 * sizeof(struct Jz4740_lcd_descriptor);
195.411 +}
195.412 +
195.413 +
195.414 +
195.415 +// Functions returning addresses of each data region.
195.416 +// The base parameter permits the retrieval of virtual or physical addresses.
195.417 +
195.418 +l4_addr_t
195.419 +Lcd_jz4740_chip::get_palette(l4_addr_t base)
195.420 +{
195.421 + // Use memory at the end of the allocated region for the palette.
195.422 +
195.423 + return base + (get_panels() * get_aligned_size()) - get_aligned_palette_size();
195.424 +}
195.425 +
195.426 +l4_addr_t
195.427 +Lcd_jz4740_chip::get_framebuffer(int panel, l4_addr_t base)
195.428 +{
195.429 + // Framebuffers for panels are allocated at the start of the region.
195.430 +
195.431 + return base + (panel * get_aligned_size());
195.432 +}
195.433 +
195.434 +
195.435 +
195.436 +// Palette initialisation.
195.437 +
195.438 +void
195.439 +Lcd_jz4740_chip::init_palette(l4_addr_t palette)
195.440 +{
195.441 + uint8_t colours = 1 << (_panel->bpp);
195.442 + uint16_t *entry = (uint16_t *) palette;
195.443 + uint16_t *end = entry + colours;
195.444 + uint8_t value = 0;
195.445 +
195.446 + while (entry < end)
195.447 + {
195.448 + switch (_panel->bpp)
195.449 + {
195.450 + case 4:
195.451 + *entry = rgb4_to_rgb16(value);
195.452 + break;
195.453 +
195.454 + case 8:
195.455 + *entry = rgb8_to_rgb16(value);
195.456 + break;
195.457 +
195.458 + default:
195.459 + break;
195.460 + }
195.461 +
195.462 + value++;
195.463 + entry++;
195.464 + }
195.465 +}
195.466 +
195.467 +
195.468 +
195.469 +// Return colour depth control value.
195.470 +// NOTE: Not supporting JZ4780 options.
195.471 +
195.472 +uint32_t
195.473 +Lcd_jz4740_chip::_control_bpp()
195.474 +{
195.475 + switch (_panel->bpp)
195.476 + {
195.477 + case 1: return Control_bpp_1bpp;
195.478 + case 2: return Control_bpp_2bpp;
195.479 + case 3 ... 4: return Control_bpp_4bpp;
195.480 + case 5 ... 8: return Control_bpp_8bpp;
195.481 + case 9 ... 15: return Control_bpp_15bpp | (Rgb_mode_555 << Control_rgb_mode);
195.482 + case 17 ... 18: return Control_bpp_18bpp;
195.483 + case 19 ... 32: return Control_bpp_24bpp;
195.484 + case 16:
195.485 + default: return Control_bpp_16bpp;
195.486 + }
195.487 +}
195.488 +
195.489 +// Return a panel-related control value.
195.490 +
195.491 +uint32_t
195.492 +Lcd_jz4740_chip::_control_panel()
195.493 +{
195.494 + if (have_stn_panel())
195.495 + return _control_stn_frc();
195.496 + else
195.497 + return 0;
195.498 +}
195.499 +
195.500 +// Return a STN-related control value.
195.501 +
195.502 +uint32_t
195.503 +Lcd_jz4740_chip::_control_stn_frc()
195.504 +{
195.505 + if (_panel->bpp <= 2)
195.506 + return Frc_greyscales_2;
195.507 + if (_panel->bpp <= 4)
195.508 + return Frc_greyscales_4;
195.509 + return Frc_greyscales_16;
195.510 +}
195.511 +
195.512 +// Return a transfer-related control value.
195.513 +
195.514 +uint32_t
195.515 +Lcd_jz4740_chip::_control_transfer()
195.516 +{
195.517 + uint32_t length;
195.518 +
195.519 + switch (_burst_size)
195.520 + {
195.521 + case 4: length = Burst_length_4; break;
195.522 + case 8: length = Burst_length_8; break;
195.523 + case 32: length = Burst_length_32; break;
195.524 + case 64: length = Burst_length_64; break;
195.525 + case 16:
195.526 + default: length = Burst_length_16; break;
195.527 + }
195.528 +
195.529 + return (length << Control_burst_length) | (1 << Control_out_underrun);
195.530 +}
195.531 +
195.532 +// STN panel-specific initialisation.
195.533 +
195.534 +void
195.535 +Lcd_jz4740_chip::_init_stn()
195.536 +{
195.537 + // Divide the height by the number of panels.
195.538 +
195.539 + uint32_t height = _panel->height / get_panels();
195.540 +
195.541 + // Since the value is log2(pins), 1 << value yields the number of pins.
195.542 +
195.543 + int pins = 1 << ((_panel->config & Config_stn_pins_mask) >> Jz4740_lcd_config_stn_pins);
195.544 +
195.545 + // Round parameters up to a multiple of the number of pins.
195.546 +
195.547 + uint32_t hsync = align(_panel->hsync, pins);
195.548 + uint32_t line_start = align(_panel->line_start, pins);
195.549 + uint32_t line_end = align(_panel->line_end, pins);
195.550 +
195.551 + // Define the start and end positions of visible data on a line and in a frame.
195.552 + // Visible frame data is anchored at line zero, with the start region
195.553 + // preceding this line (and thus appearing at the end of the preceding frame).
195.554 +
195.555 + uint32_t line_start_pos = line_start;
195.556 + uint32_t line_end_pos = line_start_pos + _panel->width;
195.557 + uint32_t frame_start_pos = 0;
195.558 + uint32_t frame_end_pos = frame_start_pos + height;
195.559 +
195.560 + // Define sync pulse locations, with hsync occurring after the visible data.
195.561 +
195.562 + _regs[Lcd_hsync] = encode_pair(line_end_pos, line_end_pos + hsync);
195.563 + _regs[Lcd_vsync] = encode_pair(0, _panel->vsync);
195.564 +
195.565 + // Set the display area and limits.
195.566 +
195.567 + _regs[Vertical_area] = encode_pair(line_end_pos + hsync + line_end,
195.568 + frame_end_pos + _panel->vsync + _panel->frame_end + _panel->frame_start);
195.569 +
195.570 + _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos);
195.571 + _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos);
195.572 +
195.573 + // Set the AC bias signal.
195.574 +
195.575 + _regs[Lcd_ps] = encode_pair(0, _panel->frame_start + height + _panel->vsync + _panel->frame_end);
195.576 +}
195.577 +
195.578 +// TFT panel-specific initialisation.
195.579 +
195.580 +void
195.581 +Lcd_jz4740_chip::_init_tft()
195.582 +{
195.583 + // Define the start and end positions of visible data on a line and in a frame.
195.584 +
195.585 + uint32_t line_start_pos = _panel->line_start + _panel->hsync;
195.586 + uint32_t line_end_pos = line_start_pos + _panel->width;
195.587 + uint32_t frame_start_pos = _panel->frame_start + _panel->vsync;
195.588 + uint32_t frame_end_pos = frame_start_pos + _panel->height;
195.589 +
195.590 + // Define sync pulse locations, with pulses appearing before visible data.
195.591 +
195.592 + _regs[Lcd_hsync] = encode_pair(0, _panel->hsync);
195.593 + _regs[Lcd_vsync] = encode_pair(0, _panel->vsync);
195.594 +
195.595 + // Set the display area and limits.
195.596 +
195.597 + _regs[Vertical_area] = encode_pair(line_end_pos + _panel->line_end,
195.598 + frame_end_pos + _panel->frame_end);
195.599 +
195.600 + _regs[Display_hlimits] = encode_pair(line_start_pos, line_end_pos);
195.601 + _regs[Display_vlimits] = encode_pair(frame_start_pos, frame_end_pos);
195.602 +}
195.603 +
195.604 +// Initialise the panel.
195.605 +// NOTE: Only generic STN and TFT panels are supported.
195.606 +
195.607 +void
195.608 +Lcd_jz4740_chip::_init_panel()
195.609 +{
195.610 + if (have_stn_panel())
195.611 + _init_stn();
195.612 + else
195.613 + switch (_mode())
195.614 + {
195.615 + case Jz4740_lcd_mode_tft_generic:
195.616 + case Jz4740_lcd_mode_tft_casio:
195.617 + case Jz4740_lcd_mode_tft_serial: _init_tft();
195.618 +
195.619 + default: break;
195.620 + }
195.621 +}
195.622 +
195.623 +// Initialise a DMA descriptor.
195.624 +
195.625 +void
195.626 +Lcd_jz4740_chip::_set_descriptor(struct Jz4740_lcd_descriptor &desc,
195.627 + l4_addr_t source, l4_size_t size,
195.628 + struct Jz4740_lcd_descriptor *next,
195.629 + uint32_t flags)
195.630 +{
195.631 + // In the command, indicate the number of words from the source for transfer.
195.632 +
195.633 + desc.next = next;
195.634 + desc.source = source;
195.635 + desc.identifier = 0;
195.636 + desc.command = ((size / sizeof(uint32_t)) & Command_buffer_length_mask) | flags;
195.637 +}
195.638 +
195.639 +
195.640 +
195.641 +// Initialise the LCD controller with the memory, panel and framebuffer details.
195.642 +// Any palette must be initialised separately using get_palette and init_palette.
195.643 +
195.644 +void
195.645 +Lcd_jz4740_chip::config(struct Jz4740_lcd_descriptor *desc_vaddr,
195.646 + struct Jz4740_lcd_descriptor *desc_paddr,
195.647 + l4_addr_t fb_paddr)
195.648 +{
195.649 + int have_palette = (_panel->bpp <= 8);
195.650 +
195.651 + // Provide the first framebuffer descriptor in single and dual modes.
195.652 + // Flip back and forth between any palette and the framebuffer.
195.653 +
195.654 + _set_descriptor(desc_vaddr[0], get_framebuffer(0, fb_paddr),
195.655 + get_screen_size(),
195.656 + have_palette ? desc_paddr + 2 : desc_paddr);
195.657 +
195.658 + // Provide the second framebuffer descriptor only in dual-panel mode.
195.659 + // Only employ this descriptor in the second DMA channel.
195.660 +
195.661 + if (get_panels() == 2)
195.662 + _set_descriptor(desc_vaddr[1], get_framebuffer(1, fb_paddr),
195.663 + get_screen_size(),
195.664 + desc_paddr + 1);
195.665 +
195.666 + // Initialise palette descriptor details for lower colour depths.
195.667 +
195.668 + if (have_palette)
195.669 + _set_descriptor(desc_vaddr[2], get_palette(fb_paddr),
195.670 + get_palette_size(),
195.671 + desc_paddr,
195.672 + Command_palette_buffer);
195.673 +
195.674 + // Flush cached structure data.
195.675 +
195.676 + l4_cache_clean_data((unsigned long) desc_vaddr,
195.677 + (unsigned long) desc_vaddr + get_descriptors_size());
195.678 +
195.679 + // Configure DMA by setting frame descriptor addresses.
195.680 +
195.681 + // Provide the palette descriptor address first, if employed.
195.682 +
195.683 + _regs[Desc_address_0] = (uint32_t) (have_palette ? desc_paddr + 2 : desc_paddr);
195.684 +
195.685 + // Provide a descriptor for the second DMA channel in dual-panel mode.
195.686 +
195.687 + if (get_panels() == 2)
195.688 + _regs[Desc_address_1] = (uint32_t) (desc_paddr + 1);
195.689 +
195.690 + // Initialise panel-related registers.
195.691 +
195.692 + _init_panel();
195.693 +
195.694 + // Initialise the control and configuration registers.
195.695 +
195.696 + _regs[Lcd_control] = _control_panel() | _control_bpp() | _control_transfer();
195.697 + _regs[Lcd_config] = _panel->config;
195.698 +}
195.699 +
195.700 +
195.701 +
195.702 +// C language interface functions.
195.703 +
195.704 +void *
195.705 +jz4740_lcd_init(l4_addr_t lcd_base, struct Jz4740_lcd_panel *panel)
195.706 +{
195.707 + return (void *) new Lcd_jz4740_chip(lcd_base, panel);
195.708 +}
195.709 +
195.710 +void
195.711 +jz4740_lcd_config(void *lcd, struct Jz4740_lcd_descriptor *desc_vaddr,
195.712 + struct Jz4740_lcd_descriptor *desc_paddr,
195.713 + l4_addr_t fb_paddr)
195.714 +{
195.715 + static_cast<Lcd_jz4740_chip *>(lcd)->config(desc_vaddr, desc_paddr, fb_paddr);
195.716 +}
195.717 +
195.718 +void
195.719 +jz4740_lcd_disable(void *lcd)
195.720 +{
195.721 + static_cast<Lcd_jz4740_chip *>(lcd)->disable();
195.722 +}
195.723 +
195.724 +void
195.725 +jz4740_lcd_disable_quick(void *lcd)
195.726 +{
195.727 + static_cast<Lcd_jz4740_chip *>(lcd)->disable_quick();
195.728 +}
195.729 +
195.730 +void
195.731 +jz4740_lcd_enable(void *lcd)
195.732 +{
195.733 + static_cast<Lcd_jz4740_chip *>(lcd)->enable();
195.734 +}
195.735 +
195.736 +int
195.737 +jz4740_lcd_get_pixel_clock(void *lcd)
195.738 +{
195.739 + return static_cast<Lcd_jz4740_chip *>(lcd)->get_pixel_clock();
195.740 +}
195.741 +
195.742 +l4_addr_t
195.743 +jz4740_lcd_get_palette(void *lcd, l4_addr_t base)
195.744 +{
195.745 + return static_cast<Lcd_jz4740_chip *>(lcd)->get_palette(base);
195.746 +}
195.747 +
195.748 +void
195.749 +jz4740_lcd_init_palette(void *lcd, l4_addr_t palette)
195.750 +{
195.751 + static_cast<Lcd_jz4740_chip *>(lcd)->init_palette(palette);
195.752 +}
196.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
196.2 +++ b/pkg/devices/lib/pwm/Makefile Sun May 13 01:34:16 2018 +0200
196.3 @@ -0,0 +1,8 @@
196.4 +PKGDIR ?= ../..
196.5 +L4DIR ?= $(PKGDIR)/../..
196.6 +
196.7 +TARGET := include src
196.8 +
196.9 +include $(L4DIR)/mk/subdir.mk
196.10 +
196.11 +src: include
197.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
197.2 +++ b/pkg/devices/lib/pwm/include/Makefile Sun May 13 01:34:16 2018 +0200
197.3 @@ -0,0 +1,4 @@
197.4 +PKGDIR = ../../..
197.5 +L4DIR ?= $(PKGDIR)/../..
197.6 +
197.7 +include $(L4DIR)/mk/include.mk
198.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
198.2 +++ b/pkg/devices/lib/pwm/include/pwm-jz4730.h Sun May 13 01:34:16 2018 +0200
198.3 @@ -0,0 +1,79 @@
198.4 +/*
198.5 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
198.6 + *
198.7 + * This program is free software; you can redistribute it and/or
198.8 + * modify it under the terms of the GNU General Public License as
198.9 + * published by the Free Software Foundation; either version 2 of
198.10 + * the License, or (at your option) any later version.
198.11 + *
198.12 + * This program is distributed in the hope that it will be useful,
198.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
198.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
198.15 + * GNU General Public License for more details.
198.16 + *
198.17 + * You should have received a copy of the GNU General Public License
198.18 + * along with this program; if not, write to the Free Software
198.19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
198.20 + * Boston, MA 02110-1301, USA
198.21 + */
198.22 +
198.23 +#pragma once
198.24 +
198.25 +#include <l4/sys/types.h>
198.26 +#include <stdint.h>
198.27 +
198.28 +
198.29 +
198.30 +/* Value types. */
198.31 +
198.32 +enum Jz4730_pwm_shutdown_mode
198.33 +{
198.34 + Jz4730_pwm_shutdown_graceful = 0,
198.35 + Jz4730_pwm_shutdown_abrupt = 1,
198.36 +};
198.37 +
198.38 +
198.39 +
198.40 +#ifdef __cplusplus
198.41 +
198.42 +#include <l4/devices/hw_register_block.h>
198.43 +
198.44 +/* A simple abstraction for accessing the PWM registers. */
198.45 +
198.46 +class Pwm_jz4730_chip
198.47 +{
198.48 +private:
198.49 + l4_addr_t _start, _end;
198.50 + Hw::Register_block<32> _regs;
198.51 +
198.52 +public:
198.53 + Pwm_jz4730_chip(l4_addr_t start, l4_addr_t end);
198.54 +
198.55 + void disable();
198.56 + void enable();
198.57 + void set_shutdown_mode(enum Jz4730_pwm_shutdown_mode mode);
198.58 +
198.59 + void set_control(uint8_t control);
198.60 + void set_duty(uint16_t duty);
198.61 + void set_period(uint16_t period);
198.62 +};
198.63 +
198.64 +#endif /* __cplusplus */
198.65 +
198.66 +
198.67 +
198.68 +/* C language interface. */
198.69 +
198.70 +EXTERN_C_BEGIN
198.71 +
198.72 +void *jz4730_pwm_init(l4_addr_t start, l4_addr_t end);
198.73 +
198.74 +void jz4730_pwm_disable(void *pwm);
198.75 +void jz4730_pwm_enable(void *pwm);
198.76 +void jz4730_pwm_set_shutdown_mode(void *pwm, enum Jz4730_pwm_shutdown_mode mode);
198.77 +
198.78 +void jz4730_pwm_set_control(void *pwm, uint8_t control);
198.79 +void jz4730_pwm_set_duty(void *pwm, uint16_t duty);
198.80 +void jz4730_pwm_set_period(void *pwm, uint16_t period);
198.81 +
198.82 +EXTERN_C_END
199.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
199.2 +++ b/pkg/devices/lib/pwm/src/Makefile Sun May 13 01:34:16 2018 +0200
199.3 @@ -0,0 +1,13 @@
199.4 +PKGDIR ?= ../../..
199.5 +L4DIR ?= $(PKGDIR)/../..
199.6 +
199.7 +TARGET = libpwm.o.a
199.8 +PC_FILENAME := libdrivers-pwm
199.9 +
199.10 +SRC_CC := jz4730.cc
199.11 +
199.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/pwm/include
199.13 +
199.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common
199.15 +
199.16 +include $(L4DIR)/mk/lib.mk
200.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
200.2 +++ b/pkg/devices/lib/pwm/src/jz4730.cc Sun May 13 01:34:16 2018 +0200
200.3 @@ -0,0 +1,158 @@
200.4 +/*
200.5 + * Pulse width modulation peripheral support.
200.6 + *
200.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
200.8 + *
200.9 + * This program is free software; you can redistribute it and/or
200.10 + * modify it under the terms of the GNU General Public License as
200.11 + * published by the Free Software Foundation; either version 2 of
200.12 + * the License, or (at your option) any later version.
200.13 + *
200.14 + * This program is distributed in the hope that it will be useful,
200.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
200.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
200.17 + * GNU General Public License for more details.
200.18 + *
200.19 + * You should have received a copy of the GNU General Public License
200.20 + * along with this program; if not, write to the Free Software
200.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
200.22 + * Boston, MA 02110-1301, USA
200.23 + */
200.24 +
200.25 +#include <l4/devices/hw_mmio_register_block.h>
200.26 +#include "pwm-jz4730.h"
200.27 +
200.28 +
200.29 +
200.30 +enum Regs : unsigned
200.31 +{
200.32 + Pwm_control = 0x000, // CTR
200.33 + Pwm_period = 0x004, // PER
200.34 + Pwm_duty = 0x008, // DUT
200.35 +};
200.36 +
200.37 +enum Control_bits : unsigned
200.38 +{
200.39 + Pwm_enable = 7,
200.40 + Pwm_abrupt_shutdown = 6,
200.41 + Pwm_prescale_mask = 0x3f,
200.42 +};
200.43 +
200.44 +enum Duty_bits : unsigned
200.45 +{
200.46 + Pwm_duty_full = 10,
200.47 + Pwm_duty_mask = 0x3ff,
200.48 +};
200.49 +
200.50 +enum Period_bits : unsigned
200.51 +{
200.52 + Pwm_period_mask = 0x3ff,
200.53 +};
200.54 +
200.55 +
200.56 +
200.57 +// If implemented as a Hw::Device, various properties would be
200.58 +// initialised in the constructor and obtained from the device tree
200.59 +// definitions.
200.60 +
200.61 +Pwm_jz4730_chip::Pwm_jz4730_chip(l4_addr_t start, l4_addr_t end)
200.62 +: _start(start), _end(end)
200.63 +{
200.64 + _regs = new Hw::Mmio_register_block<32>(_start);
200.65 +
200.66 + // add_cid("pwm");
200.67 + // add_cid("pwm-jz4730");
200.68 +}
200.69 +
200.70 +void
200.71 +Pwm_jz4730_chip::set_control(uint8_t control)
200.72 +{
200.73 + // This allows the setting of the actual control bits.
200.74 +
200.75 + _regs[Pwm_control] = control;
200.76 +}
200.77 +
200.78 +void
200.79 +Pwm_jz4730_chip::disable()
200.80 +{
200.81 + _regs[Pwm_control] = _regs[Pwm_control] & ~(1 << Pwm_enable);
200.82 +}
200.83 +
200.84 +void
200.85 +Pwm_jz4730_chip::enable()
200.86 +{
200.87 + _regs[Pwm_control] = _regs[Pwm_control] | (1 << Pwm_enable);
200.88 +}
200.89 +
200.90 +void
200.91 +Pwm_jz4730_chip::set_shutdown_mode(enum Jz4730_pwm_shutdown_mode mode)
200.92 +{
200.93 + if (mode == Jz4730_pwm_shutdown_graceful)
200.94 + _regs[Pwm_control] = _regs[Pwm_control] & ~(1 << Pwm_abrupt_shutdown);
200.95 + else
200.96 + _regs[Pwm_control] = _regs[Pwm_control] | (1 << Pwm_abrupt_shutdown);
200.97 +}
200.98 +
200.99 +void
200.100 +Pwm_jz4730_chip::set_duty(uint16_t duty)
200.101 +{
200.102 + // This deselects full duty, if it were set.
200.103 + // NOTE: A way of selecting full duty is required.
200.104 +
200.105 + _regs[Pwm_duty] = (_regs[Pwm_duty] & ~(Pwm_duty_mask | (1 << Pwm_duty_full))) |
200.106 + (duty & Pwm_duty_mask);
200.107 +}
200.108 +
200.109 +void
200.110 +Pwm_jz4730_chip::set_period(uint16_t period)
200.111 +{
200.112 + _regs[Pwm_period] = (_regs[Pwm_period] & ~Pwm_period_mask) |
200.113 + (period & Pwm_period_mask);
200.114 +}
200.115 +
200.116 +
200.117 +
200.118 +
200.119 +// C language interface functions.
200.120 +
200.121 +void *
200.122 +jz4730_pwm_init(l4_addr_t start, l4_addr_t end)
200.123 +{
200.124 + return (void *) new Pwm_jz4730_chip(start, end);
200.125 +}
200.126 +
200.127 +void
200.128 +jz4730_pwm_disable(void *pwm)
200.129 +{
200.130 + static_cast<Pwm_jz4730_chip *>(pwm)->disable();
200.131 +}
200.132 +
200.133 +void
200.134 +jz4730_pwm_enable(void *pwm)
200.135 +{
200.136 + static_cast<Pwm_jz4730_chip *>(pwm)->enable();
200.137 +}
200.138 +
200.139 +void
200.140 +jz4730_pwm_set_shutdown_mode(void *pwm, enum Jz4730_pwm_shutdown_mode mode)
200.141 +{
200.142 + static_cast<Pwm_jz4730_chip *>(pwm)->set_shutdown_mode(mode);
200.143 +}
200.144 +
200.145 +void
200.146 +jz4730_pwm_set_control(void *pwm, uint8_t control)
200.147 +{
200.148 + static_cast<Pwm_jz4730_chip *>(pwm)->set_control(control);
200.149 +}
200.150 +
200.151 +void
200.152 +jz4730_pwm_set_duty(void *pwm, uint16_t duty)
200.153 +{
200.154 + static_cast<Pwm_jz4730_chip *>(pwm)->set_duty(duty);
200.155 +}
200.156 +
200.157 +void
200.158 +jz4730_pwm_set_period(void *pwm, uint16_t period)
200.159 +{
200.160 + static_cast<Pwm_jz4730_chip *>(pwm)->set_period(period);
200.161 +}
201.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
201.2 +++ b/pkg/devices/panel/Makefile Sun May 13 01:34:16 2018 +0200
201.3 @@ -0,0 +1,8 @@
201.4 +PKGDIR ?= ..
201.5 +L4DIR ?= $(PKGDIR)/../..
201.6 +
201.7 +TARGET := include src
201.8 +
201.9 +include $(L4DIR)/mk/subdir.mk
201.10 +
201.11 +src: include
202.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
202.2 +++ b/pkg/devices/panel/include/Makefile Sun May 13 01:34:16 2018 +0200
202.3 @@ -0,0 +1,6 @@
202.4 +PKGDIR = ../..
202.5 +L4DIR ?= $(PKGDIR)/../..
202.6 +
202.7 +PC_FILENAME := libdevice-panel-ops
202.8 +
202.9 +include $(L4DIR)/mk/include.mk
203.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
203.2 +++ b/pkg/devices/panel/include/panel-client.h Sun May 13 01:34:16 2018 +0200
203.3 @@ -0,0 +1,39 @@
203.4 +/*
203.5 + * Panel client to access panel servers.
203.6 + *
203.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
203.8 + *
203.9 + * This program is free software; you can redistribute it and/or
203.10 + * modify it under the terms of the GNU General Public License as
203.11 + * published by the Free Software Foundation; either version 2 of
203.12 + * the License, or (at your option) any later version.
203.13 + *
203.14 + * This program is distributed in the hope that it will be useful,
203.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
203.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
203.17 + * GNU General Public License for more details.
203.18 + *
203.19 + * You should have received a copy of the GNU General Public License
203.20 + * along with this program; if not, write to the Free Software
203.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
203.22 + * Boston, MA 02110-1301, USA
203.23 + */
203.24 +
203.25 +#pragma once
203.26 +
203.27 +#ifdef __cplusplus
203.28 +
203.29 +#include <l4/re/dataspace>
203.30 +#include <l4/re/env>
203.31 +
203.32 +#include <stdint.h>
203.33 +
203.34 +class Panel_device_interface : public L4::Kobject_t<Panel_device_interface, L4::Kobject>
203.35 +{
203.36 + L4_KOBJECT(Panel_device_interface)
203.37 +
203.38 +public:
203.39 + int get_panel(uint8_t *data, unsigned long datalen) throw();
203.40 +};
203.41 +
203.42 +#endif
204.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
204.2 +++ b/pkg/devices/panel/include/panel-ops.h Sun May 13 01:34:16 2018 +0200
204.3 @@ -0,0 +1,24 @@
204.4 +/*
204.5 + * Panel server operations.
204.6 + *
204.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
204.8 + *
204.9 + * This program is free software; you can redistribute it and/or
204.10 + * modify it under the terms of the GNU General Public License as
204.11 + * published by the Free Software Foundation; either version 2 of
204.12 + * the License, or (at your option) any later version.
204.13 + *
204.14 + * This program is distributed in the hope that it will be useful,
204.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
204.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
204.17 + * GNU General Public License for more details.
204.18 + *
204.19 + * You should have received a copy of the GNU General Public License
204.20 + * along with this program; if not, write to the Free Software
204.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
204.22 + * Boston, MA 02110-1301, USA
204.23 + */
204.24 +
204.25 +#pragma once
204.26 +
204.27 +enum { Panel_op_get_panel };
205.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
205.2 +++ b/pkg/devices/panel/include/panel-server.h Sun May 13 01:34:16 2018 +0200
205.3 @@ -0,0 +1,49 @@
205.4 +/*
205.5 + * Common panel server functionality.
205.6 + *
205.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
205.8 + *
205.9 + * This program is free software; you can redistribute it and/or
205.10 + * modify it under the terms of the GNU General Public License as
205.11 + * published by the Free Software Foundation; either version 2 of
205.12 + * the License, or (at your option) any later version.
205.13 + *
205.14 + * This program is distributed in the hope that it will be useful,
205.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
205.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
205.17 + * GNU General Public License for more details.
205.18 + *
205.19 + * You should have received a copy of the GNU General Public License
205.20 + * along with this program; if not, write to the Free Software
205.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
205.22 + * Boston, MA 02110-1301, USA
205.23 + */
205.24 +
205.25 +#pragma once
205.26 +
205.27 +#ifdef __cplusplus
205.28 +
205.29 +#include <l4/cxx/ipc_server>
205.30 +#include <l4/re/dataspace>
205.31 +#include <l4/re/env>
205.32 +
205.33 +/* Server object to provide panel data access. */
205.34 +
205.35 +class Panel_server : public L4::Server_object_t<L4::Kobject>
205.36 +{
205.37 +private:
205.38 + void *_panel;
205.39 + unsigned long _size;
205.40 +
205.41 +public:
205.42 + /* Initialise the server with an opaque pointer to the panel data and the
205.43 + size of the data. */
205.44 +
205.45 + explicit Panel_server(void *panel, unsigned long size)
205.46 + : _panel(panel), _size(size)
205.47 + {}
205.48 +
205.49 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
205.50 +};
205.51 +
205.52 +#endif
206.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
206.2 +++ b/pkg/devices/panel/src/Makefile Sun May 13 01:34:16 2018 +0200
206.3 @@ -0,0 +1,9 @@
206.4 +PKGDIR ?= ../..
206.5 +L4DIR ?= $(PKGDIR)/../..
206.6 +
206.7 +TARGET := client letux400 qi_lb60 server
206.8 +
206.9 +include $(L4DIR)/mk/subdir.mk
206.10 +
206.11 +letux400: server
206.12 +qi_lb60: server
207.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
207.2 +++ b/pkg/devices/panel/src/client/Makefile Sun May 13 01:34:16 2018 +0200
207.3 @@ -0,0 +1,13 @@
207.4 +PKGDIR ?= ../../..
207.5 +L4DIR ?= $(PKGDIR)/../..
207.6 +
207.7 +TARGET = libdevice_panel_client.o.a
207.8 +PC_FILENAME := libdevice-panel-client
207.9 +
207.10 +SRC_CC := panel-client.cc
207.11 +
207.12 +PRIVATE_INCDIR += $(PKGDIR)/panel/include
207.13 +
207.14 +REQUIRES_LIBS := l4re_c l4re_c-util
207.15 +
207.16 +include $(L4DIR)/mk/lib.mk
208.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
208.2 +++ b/pkg/devices/panel/src/client/panel-client.cc Sun May 13 01:34:16 2018 +0200
208.3 @@ -0,0 +1,46 @@
208.4 +/*
208.5 + * Panel client to access panel servers.
208.6 + *
208.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
208.8 + *
208.9 + * This program is free software; you can redistribute it and/or
208.10 + * modify it under the terms of the GNU General Public License as
208.11 + * published by the Free Software Foundation; either version 2 of
208.12 + * the License, or (at your option) any later version.
208.13 + *
208.14 + * This program is distributed in the hope that it will be useful,
208.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
208.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
208.17 + * GNU General Public License for more details.
208.18 + *
208.19 + * You should have received a copy of the GNU General Public License
208.20 + * along with this program; if not, write to the Free Software
208.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
208.22 + * Boston, MA 02110-1301, USA
208.23 + */
208.24 +
208.25 +#include <l4/cxx/ipc_stream>
208.26 +#include <l4/re/env>
208.27 +#include <l4/sys/err.h>
208.28 +
208.29 +#include "panel-client.h"
208.30 +#include "panel-ops.h"
208.31 +
208.32 +#include <stdint.h>
208.33 +
208.34 +int
208.35 +Panel_device_interface::get_panel(uint8_t *data, unsigned long datalen) throw()
208.36 +{
208.37 + L4::Ipc::Iostream s(l4_utcb());
208.38 +
208.39 + int err = l4_error(s.call(cap(), Panel_op_get_panel));
208.40 + if (err) return err;
208.41 +
208.42 + // Obtain the message from the stream.
208.43 +
208.44 + unsigned long size = datalen;
208.45 + s >> L4::Ipc::buf_cp_in<uint8_t>(data, datalen);
208.46 +
208.47 + if (size != datalen) return -L4_EIO;
208.48 + return L4_EOK;
208.49 +}
209.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
209.2 +++ b/pkg/devices/panel/src/letux400/Makefile Sun May 13 01:34:16 2018 +0200
209.3 @@ -0,0 +1,13 @@
209.4 +PKGDIR ?= ../../..
209.5 +L4DIR ?= $(PKGDIR)/../..
209.6 +
209.7 +TARGET = dev_panel_letux400
209.8 +PC_FILENAME := devices-panel-letux400
209.9 +
209.10 +SRC_CC := panel-letux400.cc
209.11 +
209.12 +PRIVATE_INCDIR += $(PKGDIR)/panel/include
209.13 +
209.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-lcd-headers libdevice-panel-server
209.15 +
209.16 +include $(L4DIR)/mk/prog.mk
210.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
210.2 +++ b/pkg/devices/panel/src/letux400/panel-letux400.cc Sun May 13 01:34:16 2018 +0200
210.3 @@ -0,0 +1,61 @@
210.4 +/*
210.5 + * Export a panel structure.
210.6 + *
210.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
210.8 + *
210.9 + * This program is free software; you can redistribute it and/or
210.10 + * modify it under the terms of the GNU General Public License as
210.11 + * published by the Free Software Foundation; either version 2 of
210.12 + * the License, or (at your option) any later version.
210.13 + *
210.14 + * This program is distributed in the hope that it will be useful,
210.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
210.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
210.17 + * GNU General Public License for more details.
210.18 + *
210.19 + * You should have received a copy of the GNU General Public License
210.20 + * along with this program; if not, write to the Free Software
210.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
210.22 + * Boston, MA 02110-1301, USA
210.23 + */
210.24 +
210.25 +#include <l4/devices/lcd-jz4740-config.h>
210.26 +#include <l4/devices/lcd-jz4740-panel.h>
210.27 +#include "panel-server.h"
210.28 +
210.29 +#include <l4/re/util/object_registry>
210.30 +
210.31 +static struct Jz4740_lcd_panel panel = {
210.32 + .config = (
210.33 + Jz4740_lcd_mode_tft_generic
210.34 + | Jz4740_lcd_pclock_negative
210.35 + | Jz4740_lcd_hsync_negative
210.36 + | Jz4740_lcd_vsync_negative
210.37 + | Jz4740_lcd_de_positive),
210.38 +
210.39 + .width = 800,
210.40 + .height = 480,
210.41 + .bpp = 16,
210.42 + .frame_rate = 60,
210.43 + .hsync = 80,
210.44 + .vsync = 20,
210.45 + .line_start = 0,
210.46 + .line_end = 0,
210.47 + .frame_start = 0,
210.48 + .frame_end = 0,
210.49 +};
210.50 +
210.51 +static L4Re::Util::Registry_server<> server;
210.52 +
210.53 +int main(void)
210.54 +{
210.55 + /* Initialise and register a new server object. */
210.56 +
210.57 + Panel_server server_obj(&panel, sizeof(panel));
210.58 + server.registry()->register_obj(&server_obj, "panel");
210.59 +
210.60 + /* Enter the IPC server loop. */
210.61 +
210.62 + server.loop();
210.63 + return 0;
210.64 +}
211.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
211.2 +++ b/pkg/devices/panel/src/qi_lb60/Makefile Sun May 13 01:34:16 2018 +0200
211.3 @@ -0,0 +1,13 @@
211.4 +PKGDIR ?= ../../..
211.5 +L4DIR ?= $(PKGDIR)/../..
211.6 +
211.7 +TARGET = dev_panel_qi_lb60
211.8 +PC_FILENAME := devices-panel-qi_lb60
211.9 +
211.10 +SRC_CC := panel-qi_lb60.cc
211.11 +
211.12 +PRIVATE_INCDIR += $(PKGDIR)/panel/include
211.13 +
211.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-lcd-headers libdevice-panel-server
211.15 +
211.16 +include $(L4DIR)/mk/prog.mk
212.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
212.2 +++ b/pkg/devices/panel/src/qi_lb60/panel-qi_lb60.cc Sun May 13 01:34:16 2018 +0200
212.3 @@ -0,0 +1,61 @@
212.4 +/*
212.5 + * Export a panel structure.
212.6 + *
212.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
212.8 + *
212.9 + * This program is free software; you can redistribute it and/or
212.10 + * modify it under the terms of the GNU General Public License as
212.11 + * published by the Free Software Foundation; either version 2 of
212.12 + * the License, or (at your option) any later version.
212.13 + *
212.14 + * This program is distributed in the hope that it will be useful,
212.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
212.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
212.17 + * GNU General Public License for more details.
212.18 + *
212.19 + * You should have received a copy of the GNU General Public License
212.20 + * along with this program; if not, write to the Free Software
212.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
212.22 + * Boston, MA 02110-1301, USA
212.23 + */
212.24 +
212.25 +#include <l4/devices/lcd-jz4740-config.h>
212.26 +#include <l4/devices/lcd-jz4740-panel.h>
212.27 +#include "panel-server.h"
212.28 +
212.29 +#include <l4/re/util/object_registry>
212.30 +
212.31 +static struct Jz4740_lcd_panel panel = {
212.32 + .config = (
212.33 + Jz4740_lcd_mode_tft_serial
212.34 + | Jz4740_lcd_pclock_negative
212.35 + | Jz4740_lcd_hsync_negative
212.36 + | Jz4740_lcd_vsync_negative
212.37 + | Jz4740_lcd_de_positive),
212.38 +
212.39 + .width = 320,
212.40 + .height = 240,
212.41 + .bpp = 32,
212.42 + .frame_rate = 70,
212.43 + .hsync = 1,
212.44 + .vsync = 1,
212.45 + .line_start = 140,
212.46 + .line_end = 273,
212.47 + .frame_start = 20,
212.48 + .frame_end = 1,
212.49 +};
212.50 +
212.51 +static L4Re::Util::Registry_server<> server;
212.52 +
212.53 +int main(void)
212.54 +{
212.55 + /* Initialise and register a new server object. */
212.56 +
212.57 + Panel_server server_obj(&panel, sizeof(panel));
212.58 + server.registry()->register_obj(&server_obj, "panel");
212.59 +
212.60 + /* Enter the IPC server loop. */
212.61 +
212.62 + server.loop();
212.63 + return 0;
212.64 +}
213.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
213.2 +++ b/pkg/devices/panel/src/server/Makefile Sun May 13 01:34:16 2018 +0200
213.3 @@ -0,0 +1,13 @@
213.4 +PKGDIR ?= ../../..
213.5 +L4DIR ?= $(PKGDIR)/../..
213.6 +
213.7 +TARGET = libdevice_panel_server.o.a
213.8 +PC_FILENAME := libdevice-panel-server
213.9 +
213.10 +SRC_CC := panel-server.cc
213.11 +
213.12 +PRIVATE_INCDIR += $(PKGDIR)/panel/include
213.13 +
213.14 +REQUIRES_LIBS := l4re_c l4re_c-util
213.15 +
213.16 +include $(L4DIR)/mk/lib.mk
214.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
214.2 +++ b/pkg/devices/panel/src/server/panel-server.cc Sun May 13 01:34:16 2018 +0200
214.3 @@ -0,0 +1,53 @@
214.4 +/*
214.5 + * Common panel server functionality.
214.6 + *
214.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
214.8 + *
214.9 + * This program is free software; you can redistribute it and/or
214.10 + * modify it under the terms of the GNU General Public License as
214.11 + * published by the Free Software Foundation; either version 2 of
214.12 + * the License, or (at your option) any later version.
214.13 + *
214.14 + * This program is distributed in the hope that it will be useful,
214.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
214.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
214.17 + * GNU General Public License for more details.
214.18 + *
214.19 + * You should have received a copy of the GNU General Public License
214.20 + * along with this program; if not, write to the Free Software
214.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
214.22 + * Boston, MA 02110-1301, USA
214.23 + */
214.24 +
214.25 +#include "panel-client.h"
214.26 +#include "panel-server.h"
214.27 +#include "panel-ops.h"
214.28 +
214.29 +#include <l4/cxx/ipc_server>
214.30 +#include <l4/re/env>
214.31 +#include <l4/sys/typeinfo_svr>
214.32 +#include <l4/util/util.h>
214.33 +
214.34 +/* Handle invocations. */
214.35 +
214.36 +int
214.37 +Panel_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
214.38 +{
214.39 + l4_msgtag_t tag;
214.40 +
214.41 + (void) obj;
214.42 + ios >> tag;
214.43 +
214.44 + switch (tag.label())
214.45 + {
214.46 + case L4::Meta::Protocol:
214.47 + return L4::Util::handle_meta_request<Panel_device_interface>(ios);
214.48 +
214.49 + case Panel_op_get_panel:
214.50 + ios << L4::Ipc::buf_cp_out<uint8_t>((uint8_t *) _panel, _size);
214.51 + return L4_EOK;
214.52 +
214.53 + default:
214.54 + return -L4_EBADPROTO;
214.55 + }
214.56 +}
215.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
215.2 +++ b/pkg/devices/pwm/Makefile Sun May 13 01:34:16 2018 +0200
215.3 @@ -0,0 +1,8 @@
215.4 +PKGDIR ?= ..
215.5 +L4DIR ?= $(PKGDIR)/../..
215.6 +
215.7 +TARGET := include src
215.8 +
215.9 +include $(L4DIR)/mk/subdir.mk
215.10 +
215.11 +src: include
216.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
216.2 +++ b/pkg/devices/pwm/include/Makefile Sun May 13 01:34:16 2018 +0200
216.3 @@ -0,0 +1,4 @@
216.4 +PKGDIR = ../..
216.5 +L4DIR ?= $(PKGDIR)/../..
216.6 +
216.7 +include $(L4DIR)/mk/include.mk
217.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
217.2 +++ b/pkg/devices/pwm/include/pwm-client.h Sun May 13 01:34:16 2018 +0200
217.3 @@ -0,0 +1,43 @@
217.4 +/*
217.5 + * PWM client to access PWM servers.
217.6 + *
217.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
217.8 + *
217.9 + * This program is free software; you can redistribute it and/or
217.10 + * modify it under the terms of the GNU General Public License as
217.11 + * published by the Free Software Foundation; either version 2 of
217.12 + * the License, or (at your option) any later version.
217.13 + *
217.14 + * This program is distributed in the hope that it will be useful,
217.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
217.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
217.17 + * GNU General Public License for more details.
217.18 + *
217.19 + * You should have received a copy of the GNU General Public License
217.20 + * along with this program; if not, write to the Free Software
217.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
217.22 + * Boston, MA 02110-1301, USA
217.23 + */
217.24 +
217.25 +#pragma once
217.26 +
217.27 +#ifdef __cplusplus
217.28 +
217.29 +#include <l4/re/env>
217.30 +#include "pwm-ops.h"
217.31 +
217.32 +/* PWM device interface. */
217.33 +
217.34 +class Pwm_device_interface : public L4::Kobject_t<Pwm_device_interface, L4::Kobject>
217.35 +{
217.36 + L4_KOBJECT(Pwm_device_interface)
217.37 +
217.38 +public:
217.39 + int disable() throw();
217.40 + int enable() throw();
217.41 + int set_control(int control) throw();
217.42 + int set_duty(int duty) throw();
217.43 + int set_period(int period) throw();
217.44 +};
217.45 +
217.46 +#endif
218.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
218.2 +++ b/pkg/devices/pwm/include/pwm-ops.h Sun May 13 01:34:16 2018 +0200
218.3 @@ -0,0 +1,24 @@
218.4 +/*
218.5 + * PWM server operations.
218.6 + *
218.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
218.8 + *
218.9 + * This program is free software; you can redistribute it and/or
218.10 + * modify it under the terms of the GNU General Public License as
218.11 + * published by the Free Software Foundation; either version 2 of
218.12 + * the License, or (at your option) any later version.
218.13 + *
218.14 + * This program is distributed in the hope that it will be useful,
218.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
218.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
218.17 + * GNU General Public License for more details.
218.18 + *
218.19 + * You should have received a copy of the GNU General Public License
218.20 + * along with this program; if not, write to the Free Software
218.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
218.22 + * Boston, MA 02110-1301, USA
218.23 + */
218.24 +
218.25 +#pragma once
218.26 +
218.27 +enum { Pwm_op_disable, Pwm_op_enable, Pwm_op_set_control, Pwm_op_set_duty, Pwm_op_set_period };
219.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
219.2 +++ b/pkg/devices/pwm/src/Makefile Sun May 13 01:34:16 2018 +0200
219.3 @@ -0,0 +1,6 @@
219.4 +PKGDIR ?= ../..
219.5 +L4DIR ?= $(PKGDIR)/../..
219.6 +
219.7 +TARGET := client jz4730
219.8 +
219.9 +include $(L4DIR)/mk/subdir.mk
220.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
220.2 +++ b/pkg/devices/pwm/src/client/Makefile Sun May 13 01:34:16 2018 +0200
220.3 @@ -0,0 +1,13 @@
220.4 +PKGDIR ?= ../../..
220.5 +L4DIR ?= $(PKGDIR)/../..
220.6 +
220.7 +TARGET = libdevice_pwm_client.o.a
220.8 +PC_FILENAME := libdevice-pwm-client
220.9 +
220.10 +SRC_CC := pwm-client.cc
220.11 +
220.12 +PRIVATE_INCDIR += $(PKGDIR)/pwm/include
220.13 +
220.14 +REQUIRES_LIBS := l4re_c l4re_c-util
220.15 +
220.16 +include $(L4DIR)/mk/lib.mk
221.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
221.2 +++ b/pkg/devices/pwm/src/client/pwm-client.cc Sun May 13 01:34:16 2018 +0200
221.3 @@ -0,0 +1,70 @@
221.4 +/*
221.5 + * PWM client library to access PWM servers.
221.6 + *
221.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
221.8 + *
221.9 + * This program is free software; you can redistribute it and/or
221.10 + * modify it under the terms of the GNU General Public License as
221.11 + * published by the Free Software Foundation; either version 2 of
221.12 + * the License, or (at your option) any later version.
221.13 + *
221.14 + * This program is distributed in the hope that it will be useful,
221.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
221.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
221.17 + * GNU General Public License for more details.
221.18 + *
221.19 + * You should have received a copy of the GNU General Public License
221.20 + * along with this program; if not, write to the Free Software
221.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
221.22 + * Boston, MA 02110-1301, USA
221.23 + */
221.24 +
221.25 +#include <l4/cxx/ipc_stream>
221.26 +#include <l4/re/env>
221.27 +
221.28 +#include "pwm-client.h"
221.29 +
221.30 +/* PWM device interface. */
221.31 +
221.32 +int
221.33 +Pwm_device_interface::disable() throw()
221.34 +{
221.35 + L4::Ipc::Iostream s(l4_utcb());
221.36 +
221.37 + return l4_error(s.call(cap(), Pwm_op_disable));
221.38 +}
221.39 +
221.40 +int
221.41 +Pwm_device_interface::enable() throw()
221.42 +{
221.43 + L4::Ipc::Iostream s(l4_utcb());
221.44 +
221.45 + return l4_error(s.call(cap(), Pwm_op_enable));
221.46 +}
221.47 +
221.48 +int
221.49 +Pwm_device_interface::set_control(int control) throw()
221.50 +{
221.51 + L4::Ipc::Iostream s(l4_utcb());
221.52 +
221.53 + s << control;
221.54 + return l4_error(s.call(cap(), Pwm_op_set_control));
221.55 +}
221.56 +
221.57 +int
221.58 +Pwm_device_interface::set_duty(int duty) throw()
221.59 +{
221.60 + L4::Ipc::Iostream s(l4_utcb());
221.61 +
221.62 + s << duty;
221.63 + return l4_error(s.call(cap(), Pwm_op_set_duty));
221.64 +}
221.65 +
221.66 +int
221.67 +Pwm_device_interface::set_period(int period) throw()
221.68 +{
221.69 + L4::Ipc::Iostream s(l4_utcb());
221.70 +
221.71 + s << period;
221.72 + return l4_error(s.call(cap(), Pwm_op_set_period));
221.73 +}
222.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
222.2 +++ b/pkg/devices/pwm/src/jz4730/Makefile Sun May 13 01:34:16 2018 +0200
222.3 @@ -0,0 +1,13 @@
222.4 +PKGDIR ?= ../../..
222.5 +L4DIR ?= $(PKGDIR)/../..
222.6 +
222.7 +TARGET = dev_pwm_jz4730
222.8 +PC_FILENAME := devices-pwm-jz4730
222.9 +
222.10 +SRC_CC := pwm-jz4730.cc
222.11 +
222.12 +PRIVATE_INCDIR += $(PKGDIR)/pwm/include $(PKGDIR)/util/include
222.13 +
222.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-util libdrivers-pwm libdrivers-gpio # to use GPIO device
222.15 +
222.16 +include $(L4DIR)/mk/prog.mk
223.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
223.2 +++ b/pkg/devices/pwm/src/jz4730/pwm-jz4730.cc Sun May 13 01:34:16 2018 +0200
223.3 @@ -0,0 +1,202 @@
223.4 +/*
223.5 + * Export a JZ4730 PWM peripheral as a server.
223.6 + *
223.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
223.8 + *
223.9 + * This program is free software; you can redistribute it and/or
223.10 + * modify it under the terms of the GNU General Public License as
223.11 + * published by the Free Software Foundation; either version 2 of
223.12 + * the License, or (at your option) any later version.
223.13 + *
223.14 + * This program is distributed in the hope that it will be useful,
223.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
223.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
223.17 + * GNU General Public License for more details.
223.18 + *
223.19 + * You should have received a copy of the GNU General Public License
223.20 + * along with this program; if not, write to the Free Software
223.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
223.22 + * Boston, MA 02110-1301, USA
223.23 + */
223.24 +
223.25 +#include <l4/devices/gpio-jz4730.h>
223.26 +#include <l4/devices/pwm-jz4730.h>
223.27 +
223.28 +#include <l4/cxx/ipc_server>
223.29 +#include <l4/re/env>
223.30 +#include <l4/re/util/object_registry>
223.31 +
223.32 +#include <stdint.h>
223.33 +#include <stdlib.h>
223.34 +
223.35 +#include "pwm-ops.h"
223.36 +#include "memory.h"
223.37 +
223.38 +/* Virtual addresses for the GPIO and PWM register blocks. */
223.39 +
223.40 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
223.41 +static l4_addr_t pwm_virt_base = 0, pwm_virt_base_end = 0;
223.42 +
223.43 +
223.44 +
223.45 +static int setup_memory(void)
223.46 +{
223.47 + if (get_memory("jz4730-gpio", &gpio_virt_base, &gpio_virt_base_end))
223.48 + return 1;
223.49 +
223.50 + if (get_memory("jz4730-pwm", &pwm_virt_base, &pwm_virt_base_end))
223.51 + return 1;
223.52 +
223.53 + return 0;
223.54 +}
223.55 +
223.56 +
223.57 +
223.58 +/* PWM peripheral device. */
223.59 +
223.60 +class Pwm_device_server : public L4::Server_object_t<L4::Kobject>
223.61 +{
223.62 + Pwm_jz4730_chip *_device = 0;
223.63 + int _duty, _period, _prescale;
223.64 +
223.65 +public:
223.66 + /* Associate the device with a particular memory region. */
223.67 +
223.68 + explicit Pwm_device_server(Pwm_jz4730_chip *device, int duty, int period, int prescale)
223.69 + : _device(device), _duty(duty), _period(period), _prescale(prescale)
223.70 + {
223.71 + }
223.72 +
223.73 + /* Dispatch incoming requests. */
223.74 +
223.75 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
223.76 + {
223.77 + l4_msgtag_t tag;
223.78 + int arg;
223.79 +
223.80 + (void) obj;
223.81 + ios >> tag;
223.82 +
223.83 + switch (tag.label())
223.84 + {
223.85 + case Pwm_op_disable:
223.86 + disable();
223.87 + return L4_EOK;
223.88 +
223.89 + case Pwm_op_enable:
223.90 + enable();
223.91 + return L4_EOK;
223.92 +
223.93 + case Pwm_op_set_control:
223.94 + ios >> arg;
223.95 + set_control(arg);
223.96 + return L4_EOK;
223.97 +
223.98 + case Pwm_op_set_duty:
223.99 + ios >> arg;
223.100 + set_duty(arg);
223.101 + return L4_EOK;
223.102 +
223.103 + case Pwm_op_set_period:
223.104 + ios >> arg;
223.105 + set_period(arg);
223.106 + return L4_EOK;
223.107 +
223.108 + default:
223.109 + return -L4_EBADPROTO;
223.110 + }
223.111 + }
223.112 +
223.113 + void disable()
223.114 + {
223.115 + _device->disable();
223.116 + }
223.117 +
223.118 + void enable()
223.119 + {
223.120 + set_duty(_duty);
223.121 + set_period(_period);
223.122 + set_control(0x80 | _prescale); /* enable | prescale */
223.123 + }
223.124 +
223.125 + /* Set the control register. */
223.126 +
223.127 + void set_control(uint8_t control)
223.128 + {
223.129 + _device->set_control(control);
223.130 + }
223.131 +
223.132 + /* Set the PWM duty cycle. */
223.133 +
223.134 + void set_duty(uint16_t duty)
223.135 + {
223.136 + _duty = duty;
223.137 + _device->set_duty(duty);
223.138 + }
223.139 +
223.140 + /* Set the PWM period. */
223.141 +
223.142 + void set_period(uint16_t period)
223.143 + {
223.144 + _period = period;
223.145 + _device->set_period(period);
223.146 + }
223.147 +};
223.148 +
223.149 +static L4Re::Util::Registry_server<> server;
223.150 +
223.151 +
223.152 +
223.153 +/* Initialise devices and start the server. */
223.154 +
223.155 +static void run(int number, int duty, int period, int prescale)
223.156 +{
223.157 + Pwm_jz4730_chip pwm_device(pwm_virt_base + number * 0x1000,
223.158 + pwm_virt_base + (number + 1) * 0x1000);
223.159 +
223.160 + Gpio_jz4730_chip gpio_port_c(gpio_virt_base + 2 * 0x30,
223.161 + gpio_virt_base + 3 * 0x30, 32);
223.162 +
223.163 + /* Enable the PWM output for PC30 or PC31. */
223.164 +
223.165 + gpio_port_c.config_pad(30 + number, Hw::Gpio_chip::Function_alt, 1);
223.166 +
223.167 + /* Initialise and register a new server object. */
223.168 +
223.169 + Pwm_device_server server_obj(&pwm_device, duty, period, prescale);
223.170 + server.registry()->register_obj(&server_obj, "pwm");
223.171 +
223.172 + /* Enter the IPC server loop. */
223.173 +
223.174 + server.loop();
223.175 +}
223.176 +
223.177 +
223.178 +
223.179 +/* Arguments: <PWM device number> <duty> <period> <prescale> */
223.180 +
223.181 +int main(int argc, char *argv[])
223.182 +{
223.183 + int number, duty, period, prescale;
223.184 +
223.185 + if (argc < 5) return 1;
223.186 +
223.187 + /* Interpret and restrict the device number. */
223.188 +
223.189 + number = atoi(argv[1]);
223.190 + if ((number < 0) || (number > 1)) return 1;
223.191 +
223.192 + /* Interpret and restrict the initial parameters. */
223.193 +
223.194 + duty = atoi(argv[2]);
223.195 + period = atoi(argv[3]);
223.196 + prescale = atoi(argv[4]);
223.197 + if ((duty < 0) || (period < 0) || (prescale < 0)) return 1;
223.198 +
223.199 + /* Obtain access to peripheral memory. */
223.200 +
223.201 + if (setup_memory()) return 1;
223.202 +
223.203 + run(number, duty, period, prescale);
223.204 + return 0;
223.205 +}
224.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
224.2 +++ b/pkg/devices/spi/Makefile Sun May 13 01:34:16 2018 +0200
224.3 @@ -0,0 +1,8 @@
224.4 +PKGDIR ?= ..
224.5 +L4DIR ?= $(PKGDIR)/../..
224.6 +
224.7 +TARGET := include src
224.8 +
224.9 +include $(L4DIR)/mk/subdir.mk
224.10 +
224.11 +src: include
225.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
225.2 +++ b/pkg/devices/spi/include/Makefile Sun May 13 01:34:16 2018 +0200
225.3 @@ -0,0 +1,4 @@
225.4 +PKGDIR = ../..
225.5 +L4DIR ?= $(PKGDIR)/../..
225.6 +
225.7 +include $(L4DIR)/mk/include.mk
226.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
226.2 +++ b/pkg/devices/spi/include/spi-client.h Sun May 13 01:34:16 2018 +0200
226.3 @@ -0,0 +1,39 @@
226.4 +/*
226.5 + * SPI client to access SPI servers.
226.6 + *
226.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
226.8 + *
226.9 + * This program is free software; you can redistribute it and/or
226.10 + * modify it under the terms of the GNU General Public License as
226.11 + * published by the Free Software Foundation; either version 2 of
226.12 + * the License, or (at your option) any later version.
226.13 + *
226.14 + * This program is distributed in the hope that it will be useful,
226.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
226.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
226.17 + * GNU General Public License for more details.
226.18 + *
226.19 + * You should have received a copy of the GNU General Public License
226.20 + * along with this program; if not, write to the Free Software
226.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
226.22 + * Boston, MA 02110-1301, USA
226.23 + */
226.24 +
226.25 +#pragma once
226.26 +
226.27 +#ifdef __cplusplus
226.28 +
226.29 +#include <l4/re/env>
226.30 +#include "spi-ops.h"
226.31 +
226.32 +/* SPI device interface. */
226.33 +
226.34 +class Spi_device_interface : public L4::Kobject_t<Spi_device_interface, L4::Kobject>
226.35 +{
226.36 + L4_KOBJECT(Spi_device_interface)
226.37 +
226.38 +public:
226.39 + int send(int bits, int data) throw();
226.40 +};
226.41 +
226.42 +#endif
227.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
227.2 +++ b/pkg/devices/spi/include/spi-ops.h Sun May 13 01:34:16 2018 +0200
227.3 @@ -0,0 +1,24 @@
227.4 +/*
227.5 + * SPI server operations.
227.6 + *
227.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
227.8 + *
227.9 + * This program is free software; you can redistribute it and/or
227.10 + * modify it under the terms of the GNU General Public License as
227.11 + * published by the Free Software Foundation; either version 2 of
227.12 + * the License, or (at your option) any later version.
227.13 + *
227.14 + * This program is distributed in the hope that it will be useful,
227.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
227.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
227.17 + * GNU General Public License for more details.
227.18 + *
227.19 + * You should have received a copy of the GNU General Public License
227.20 + * along with this program; if not, write to the Free Software
227.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
227.22 + * Boston, MA 02110-1301, USA
227.23 + */
227.24 +
227.25 +#pragma once
227.26 +
227.27 +enum { Spi_op_send };
228.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
228.2 +++ b/pkg/devices/spi/src/Makefile Sun May 13 01:34:16 2018 +0200
228.3 @@ -0,0 +1,6 @@
228.4 +PKGDIR ?= ../..
228.5 +L4DIR ?= $(PKGDIR)/../..
228.6 +
228.7 +TARGET := client jz4740
228.8 +
228.9 +include $(L4DIR)/mk/subdir.mk
229.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
229.2 +++ b/pkg/devices/spi/src/client/Makefile Sun May 13 01:34:16 2018 +0200
229.3 @@ -0,0 +1,13 @@
229.4 +PKGDIR ?= ../../..
229.5 +L4DIR ?= $(PKGDIR)/../..
229.6 +
229.7 +TARGET = libdevice_spi_client.o.a
229.8 +PC_FILENAME := libdevice-spi-client
229.9 +
229.10 +SRC_CC := spi-client.cc
229.11 +
229.12 +PRIVATE_INCDIR += $(PKGDIR)/spi/include
229.13 +
229.14 +REQUIRES_LIBS := l4re_c l4re_c-util
229.15 +
229.16 +include $(L4DIR)/mk/lib.mk
230.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
230.2 +++ b/pkg/devices/spi/src/client/spi-client.cc Sun May 13 01:34:16 2018 +0200
230.3 @@ -0,0 +1,36 @@
230.4 +/*
230.5 + * SPI client library to access SPI servers.
230.6 + *
230.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
230.8 + *
230.9 + * This program is free software; you can redistribute it and/or
230.10 + * modify it under the terms of the GNU General Public License as
230.11 + * published by the Free Software Foundation; either version 2 of
230.12 + * the License, or (at your option) any later version.
230.13 + *
230.14 + * This program is distributed in the hope that it will be useful,
230.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
230.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
230.17 + * GNU General Public License for more details.
230.18 + *
230.19 + * You should have received a copy of the GNU General Public License
230.20 + * along with this program; if not, write to the Free Software
230.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
230.22 + * Boston, MA 02110-1301, USA
230.23 + */
230.24 +
230.25 +#include <l4/cxx/ipc_stream>
230.26 +#include <l4/re/env>
230.27 +
230.28 +#include "spi-client.h"
230.29 +
230.30 +/* SPI device interface. */
230.31 +
230.32 +int
230.33 +Spi_device_interface::send(int bits, int data) throw()
230.34 +{
230.35 + L4::Ipc::Iostream s(l4_utcb());
230.36 +
230.37 + s << bits << data;
230.38 + return l4_error(s.call(cap(), Spi_op_send));
230.39 +}
231.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
231.2 +++ b/pkg/devices/spi/src/jz4740/Makefile Sun May 13 01:34:16 2018 +0200
231.3 @@ -0,0 +1,13 @@
231.4 +PKGDIR ?= ../../..
231.5 +L4DIR ?= $(PKGDIR)/../..
231.6 +
231.7 +TARGET = dev_spi_jz4740
231.8 +PC_FILENAME := devices-spi-jz4740
231.9 +
231.10 +SRC_CC := spi-jz4740.cc
231.11 +
231.12 +PRIVATE_INCDIR += $(PKGDIR)/spi/include $(PKGDIR)/util/include
231.13 +
231.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdevice-util libdrivers-gpio # to use GPIO device
231.15 +
231.16 +include $(L4DIR)/mk/prog.mk
232.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
232.2 +++ b/pkg/devices/spi/src/jz4740/spi-jz4740.cc Sun May 13 01:34:16 2018 +0200
232.3 @@ -0,0 +1,212 @@
232.4 +/*
232.5 + * Export JZ4740 GPIO pins as a SPI server.
232.6 + *
232.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
232.8 + *
232.9 + * This program is free software; you can redistribute it and/or
232.10 + * modify it under the terms of the GNU General Public License as
232.11 + * published by the Free Software Foundation; either version 2 of
232.12 + * the License, or (at your option) any later version.
232.13 + *
232.14 + * This program is distributed in the hope that it will be useful,
232.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
232.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
232.17 + * GNU General Public License for more details.
232.18 + *
232.19 + * You should have received a copy of the GNU General Public License
232.20 + * along with this program; if not, write to the Free Software
232.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
232.22 + * Boston, MA 02110-1301, USA
232.23 + */
232.24 +
232.25 +#include <l4/devices/gpio-jz4740.h>
232.26 +
232.27 +#include <l4/cxx/ipc_server>
232.28 +#include <l4/re/env>
232.29 +#include <l4/re/util/object_registry>
232.30 +
232.31 +#include <errno.h>
232.32 +#include <stdint.h>
232.33 +#include <stdlib.h>
232.34 +
232.35 +#include "spi-ops.h"
232.36 +#include "memory.h"
232.37 +
232.38 +/* Virtual addresses for the GPIO register block. */
232.39 +
232.40 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
232.41 +
232.42 +
232.43 +
232.44 +static int setup_memory(void)
232.45 +{
232.46 + if (get_memory("jz4740-gpio", &gpio_virt_base, &gpio_virt_base_end))
232.47 + return 1;
232.48 +
232.49 + return 0;
232.50 +}
232.51 +
232.52 +
232.53 +
232.54 +/* SPI peripheral device. */
232.55 +
232.56 +class Spi_device_server : public L4::Server_object_t<L4::Kobject>
232.57 +{
232.58 + Gpio_jz4740_chip *_clock_device = 0, *_data_device = 0, *_enable_device = 0;
232.59 + int _clock_pin, _data_pin, _enable_pin;
232.60 +
232.61 +public:
232.62 + /* Associate the device with a particular memory region. */
232.63 +
232.64 + explicit Spi_device_server(Gpio_jz4740_chip *clock_device,
232.65 + Gpio_jz4740_chip *data_device,
232.66 + Gpio_jz4740_chip *enable_device,
232.67 + int clock_pin, int data_pin, int enable_pin)
232.68 + : _clock_device(clock_device),
232.69 + _data_device(data_device),
232.70 + _enable_device(enable_device),
232.71 + _clock_pin(clock_pin), _data_pin(data_pin), _enable_pin(enable_pin)
232.72 + {
232.73 + }
232.74 +
232.75 + /* Dispatch incoming requests. */
232.76 +
232.77 + int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
232.78 + {
232.79 + l4_msgtag_t tag;
232.80 + int bits, data;
232.81 +
232.82 + (void) obj;
232.83 + ios >> tag;
232.84 +
232.85 + switch (tag.label())
232.86 + {
232.87 + case Spi_op_send:
232.88 + ios >> bits;
232.89 + ios >> data;
232.90 + send(bits, data);
232.91 + return L4_EOK;
232.92 +
232.93 + default:
232.94 + return -L4_EBADPROTO;
232.95 + }
232.96 + }
232.97 +
232.98 + /* Send a SPI command. */
232.99 +
232.100 + void send(int bits, int data)
232.101 + {
232.102 + uint32_t mask = 1 << (bits - 1);
232.103 + int bit;
232.104 +
232.105 + /* Initialise pin levels. */
232.106 +
232.107 + _enable_device->set(_enable_pin, 1);
232.108 + _clock_device->set(_clock_pin, 1);
232.109 + _data_device->set(_data_pin, 0);
232.110 +
232.111 + /* Enter the transmission state. */
232.112 +
232.113 + _enable_device->set(_enable_pin, 0);
232.114 +
232.115 + /* Clock data using the clock and data outputs. */
232.116 +
232.117 + for (bit = 0; bit < bits; bit++)
232.118 + {
232.119 + _clock_device->set(_clock_pin, 0);
232.120 + _data_device->set(_data_pin, data & mask ? 1 : 0);
232.121 + _clock_device->set(_clock_pin, 1);
232.122 + mask >>= 1;
232.123 + }
232.124 +
232.125 + _enable_device->set(_enable_pin, 1);
232.126 + }
232.127 +};
232.128 +
232.129 +static L4Re::Util::Registry_server<> server;
232.130 +
232.131 +
232.132 +
232.133 +/*
232.134 +Parse a string of the form "<port><pin>" where <port> is a single character
232.135 +whose position in the ports string indicates the port number, and where <pin> is
232.136 +either a base 10 number, a base 8 number preceded by "0", or a base 16 number
232.137 +preceded by "0x" or "0X", defined by the strtol library function.
232.138 +*/
232.139 +
232.140 +static int parse_pin(const char *s, const char *ports, int *port, int *pin)
232.141 +{
232.142 + int i = 0;
232.143 +
232.144 + if (!s || !(*s)) return 0;
232.145 +
232.146 + /* Parse prefix in character range. */
232.147 +
232.148 + while (*ports)
232.149 + {
232.150 + if (s[0] == *ports)
232.151 + {
232.152 + *port = i;
232.153 +
232.154 + /* Parse pin number. */
232.155 +
232.156 + *pin = (int) strtol(s+1, NULL, 0);
232.157 + return !errno;
232.158 + }
232.159 + ports++; i++;
232.160 + }
232.161 +
232.162 + return 0;
232.163 +}
232.164 +
232.165 +/* Arguments: <SPI clock pin> <SPI data pin> <SPI enable pin> */
232.166 +
232.167 +int main(int argc, char *argv[])
232.168 +{
232.169 + int clock_port, clock_pin, data_port, data_pin, enable_port, enable_pin;
232.170 +
232.171 + if (argc < 4) return 1;
232.172 +
232.173 + /* Interpret the pin details. */
232.174 +
232.175 + if (!parse_pin(argv[1], "ABCD", &clock_port, &clock_pin)) return 1;
232.176 + if (!parse_pin(argv[2], "ABCD", &data_port, &data_pin)) return 1;
232.177 + if (!parse_pin(argv[3], "ABCD", &enable_port, &enable_pin)) return 1;
232.178 +
232.179 + /* Obtain access to peripheral memory. */
232.180 +
232.181 + if (setup_memory()) return 1;
232.182 +
232.183 + /* Configure the clock pin. */
232.184 +
232.185 + Gpio_jz4740_chip gpio_port_clock(gpio_virt_base + clock_port * 0x100,
232.186 + gpio_virt_base + (clock_port + 1) * 0x100, 32);
232.187 +
232.188 + gpio_port_clock.setup(clock_pin, Hw::Gpio_chip::Output, 0);
232.189 +
232.190 + /* Configure the data pin. */
232.191 +
232.192 + Gpio_jz4740_chip gpio_port_data(gpio_virt_base + data_port * 0x100,
232.193 + gpio_virt_base + (data_port + 1) * 0x100, 32);
232.194 +
232.195 + gpio_port_data.setup(data_pin, Hw::Gpio_chip::Output, 0);
232.196 +
232.197 + /* Configure the enable pin. */
232.198 +
232.199 + Gpio_jz4740_chip gpio_port_enable(gpio_virt_base + enable_port * 0x100,
232.200 + gpio_virt_base + (enable_port + 1) * 0x100, 32);
232.201 +
232.202 + gpio_port_enable.setup(enable_pin, Hw::Gpio_chip::Output, 0);
232.203 +
232.204 + /* Initialise and register a new server object. */
232.205 +
232.206 + Spi_device_server server_obj(&gpio_port_clock, &gpio_port_data, &gpio_port_enable,
232.207 + clock_pin, data_pin, enable_pin);
232.208 +
232.209 + server.registry()->register_obj(&server_obj, "spi");
232.210 +
232.211 + /* Enter the IPC server loop. */
232.212 +
232.213 + server.loop();
232.214 + return 0;
232.215 +}
233.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
233.2 +++ b/pkg/devices/util/Makefile Sun May 13 01:34:16 2018 +0200
233.3 @@ -0,0 +1,8 @@
233.4 +PKGDIR ?= ..
233.5 +L4DIR ?= $(PKGDIR)/../..
233.6 +
233.7 +TARGET := include src
233.8 +
233.9 +include $(L4DIR)/mk/subdir.mk
233.10 +
233.11 +src: include
234.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
234.2 +++ b/pkg/devices/util/include/Makefile Sun May 13 01:34:16 2018 +0200
234.3 @@ -0,0 +1,4 @@
234.4 +PKGDIR = ../..
234.5 +L4DIR ?= $(PKGDIR)/../..
234.6 +
234.7 +include $(L4DIR)/mk/include.mk
235.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
235.2 +++ b/pkg/devices/util/include/dataspace.h Sun May 13 01:34:16 2018 +0200
235.3 @@ -0,0 +1,28 @@
235.4 +/*
235.5 + * Data space allocation utility functions.
235.6 + *
235.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
235.8 + *
235.9 + * This program is free software; you can redistribute it and/or
235.10 + * modify it under the terms of the GNU General Public License as
235.11 + * published by the Free Software Foundation; either version 2 of
235.12 + * the License, or (at your option) any later version.
235.13 + *
235.14 + * This program is distributed in the hope that it will be useful,
235.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
235.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
235.17 + * GNU General Public License for more details.
235.18 + *
235.19 + * You should have received a copy of the GNU General Public License
235.20 + * along with this program; if not, write to the Free Software
235.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
235.22 + * Boston, MA 02110-1301, USA
235.23 + */
235.24 +
235.25 +#pragma once
235.26 +
235.27 +#include <l4/re/dataspace>
235.28 +#include <l4/sys/capability>
235.29 +#include <l4/sys/types.h>
235.30 +
235.31 +L4::Cap<L4Re::Dataspace> allocate_data(l4_size_t mem_size, void **allocated);
236.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
236.2 +++ b/pkg/devices/util/include/memory.h Sun May 13 01:34:16 2018 +0200
236.3 @@ -0,0 +1,34 @@
236.4 +/*
236.5 + * Memory allocation utility functions.
236.6 + *
236.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
236.8 + *
236.9 + * This program is free software; you can redistribute it and/or
236.10 + * modify it under the terms of the GNU General Public License as
236.11 + * published by the Free Software Foundation; either version 2 of
236.12 + * the License, or (at your option) any later version.
236.13 + *
236.14 + * This program is distributed in the hope that it will be useful,
236.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
236.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
236.17 + * GNU General Public License for more details.
236.18 + *
236.19 + * You should have received a copy of the GNU General Public License
236.20 + * along with this program; if not, write to the Free Software
236.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
236.22 + * Boston, MA 02110-1301, USA
236.23 + */
236.24 +
236.25 +#pragma once
236.26 +
236.27 +#include <l4/io/io.h>
236.28 +#include <l4/re/env.h>
236.29 +#include <l4/util/util.h>
236.30 +
236.31 +int get_device(char const *hid, l4io_device_handle_t *dh,
236.32 + l4io_resource_handle_t *rh);
236.33 +
236.34 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
236.35 + enum l4io_resource_types_t type);
236.36 +
236.37 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end);
237.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
237.2 +++ b/pkg/devices/util/src/Makefile Sun May 13 01:34:16 2018 +0200
237.3 @@ -0,0 +1,13 @@
237.4 +PKGDIR ?= ../..
237.5 +L4DIR ?= $(PKGDIR)/../..
237.6 +
237.7 +TARGET = libdevice_util.o.a
237.8 +PC_FILENAME := libdevice-util
237.9 +
237.10 +SRC_CC := dataspace.cc memory.cc
237.11 +
237.12 +PRIVATE_INCDIR += $(PKGDIR)/util/include
237.13 +
237.14 +REQUIRES_LIBS := libio l4re_c l4re_c-util
237.15 +
237.16 +include $(L4DIR)/mk/lib.mk
238.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
238.2 +++ b/pkg/devices/util/src/dataspace.cc Sun May 13 01:34:16 2018 +0200
238.3 @@ -0,0 +1,63 @@
238.4 +/*
238.5 + * Data space allocation utility functions.
238.6 + *
238.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
238.8 + *
238.9 + * This program is free software; you can redistribute it and/or
238.10 + * modify it under the terms of the GNU General Public License as
238.11 + * published by the Free Software Foundation; either version 2 of
238.12 + * the License, or (at your option) any later version.
238.13 + *
238.14 + * This program is distributed in the hope that it will be useful,
238.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
238.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
238.17 + * GNU General Public License for more details.
238.18 + *
238.19 + * You should have received a copy of the GNU General Public License
238.20 + * along with this program; if not, write to the Free Software
238.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
238.22 + * Boston, MA 02110-1301, USA
238.23 + */
238.24 +
238.25 +#include <l4/re/dataspace>
238.26 +#include <l4/re/env>
238.27 +#include <l4/re/rm>
238.28 +#include <l4/re/util/cap_alloc>
238.29 +
238.30 +#include "dataspace.h"
238.31 +
238.32 +/*
238.33 +Allocate and map a region containing data, using the given mem_size to indicate
238.34 +the required region size, along with a pointer to be set to the allocated
238.35 +region. Return a capability which may be invalid if allocation or mapping
238.36 +failed.
238.37 +*/
238.38 +
238.39 +L4::Cap<L4Re::Dataspace> allocate_data(l4_size_t mem_size, void **allocated)
238.40 +{
238.41 + /* Obtain a capability for the allocated memory. */
238.42 +
238.43 + L4::Cap<L4Re::Dataspace> mem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
238.44 +
238.45 + if (!mem.is_valid())
238.46 + return L4::Cap<L4Re::Dataspace>::Invalid;
238.47 +
238.48 + /* Allocate memory for the data. */
238.49 +
238.50 + if (L4Re::Env::env()->mem_alloc()->alloc(mem_size, mem, L4Re::Mem_alloc::Continuous))
238.51 + {
238.52 + L4Re::Util::cap_alloc.free(mem);
238.53 + return L4::Cap<L4Re::Dataspace>::Invalid;
238.54 + }
238.55 +
238.56 + /* Map the memory to a virtual address. */
238.57 +
238.58 + if (L4Re::Env::env()->rm()->attach(allocated, mem->size(), L4Re::Rm::Search_addr,
238.59 + L4::Ipc::make_cap_rw(mem)))
238.60 + {
238.61 + L4Re::Util::cap_alloc.free(mem);
238.62 + return L4::Cap<L4Re::Dataspace>::Invalid;
238.63 + }
238.64 +
238.65 + return mem;
238.66 +}
239.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
239.2 +++ b/pkg/devices/util/src/memory.cc Sun May 13 01:34:16 2018 +0200
239.3 @@ -0,0 +1,78 @@
239.4 +/*
239.5 + * Memory allocation utility functions.
239.6 + *
239.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
239.8 + *
239.9 + * This program is free software; you can redistribute it and/or
239.10 + * modify it under the terms of the GNU General Public License as
239.11 + * published by the Free Software Foundation; either version 2 of
239.12 + * the License, or (at your option) any later version.
239.13 + *
239.14 + * This program is distributed in the hope that it will be useful,
239.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
239.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
239.17 + * GNU General Public License for more details.
239.18 + *
239.19 + * You should have received a copy of the GNU General Public License
239.20 + * along with this program; if not, write to the Free Software
239.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
239.22 + * Boston, MA 02110-1301, USA
239.23 + */
239.24 +
239.25 +#include <l4/io/io.h>
239.26 +#include <l4/re/env.h>
239.27 +#include <l4/re/c/mem_alloc.h>
239.28 +#include <l4/re/c/util/cap_alloc.h>
239.29 +#include <l4/util/util.h>
239.30 +#include <l4/vbus/vbus.h>
239.31 +
239.32 +#include "memory.h"
239.33 +
239.34 +int get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
239.35 +{
239.36 + return l4io_lookup_device(hid, dh, 0, rh);
239.37 +}
239.38 +
239.39 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
239.40 + enum l4io_resource_types_t type)
239.41 +{
239.42 + int current = 0, result = 0;
239.43 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
239.44 +
239.45 + do
239.46 + {
239.47 + result = l4vbus_get_resource(vbus, dh, current, res);
239.48 + current++;
239.49 + }
239.50 + while ((!result) && (res->type != type));
239.51 +
239.52 + return result;
239.53 +}
239.54 +
239.55 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
239.56 +{
239.57 + l4io_device_handle_t dh;
239.58 + l4io_resource_handle_t rh;
239.59 + l4io_resource_t res;
239.60 + int result;
239.61 +
239.62 + result = get_device(hid, &dh, &rh);
239.63 +
239.64 + if (result < 0)
239.65 + return result;
239.66 +
239.67 + result = get_resource(dh, &res, L4IO_RESOURCE_MEM);
239.68 +
239.69 + if (result)
239.70 + return result;
239.71 +
239.72 + result = l4io_request_iomem(res.start, res.end - res.start + 1,
239.73 + L4IO_MEM_NONCACHED, start);
239.74 +
239.75 + if (result)
239.76 + return result;
239.77 +
239.78 + *end = *start + (res.end - res.start + 1);
239.79 +
239.80 + return 0;
239.81 +}
240.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
240.2 +++ b/pkg/landfall-examples/Makefile Sun May 13 01:34:16 2018 +0200
240.3 @@ -0,0 +1,6 @@
240.4 +PKGDIR = ..
240.5 +L4DIR ?= $(PKGDIR)/../..
240.6 +
240.7 +TARGET = $(wildcard [a-z]*)
240.8 +
240.9 +include $(L4DIR)/mk/subdir.mk
241.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
241.2 +++ b/pkg/landfall-examples/ci20_cpm/Makefile Sun May 13 01:34:16 2018 +0200
241.3 @@ -0,0 +1,8 @@
241.4 +PKGDIR ?= ../..
241.5 +L4DIR ?= $(PKGDIR)/../..
241.6 +
241.7 +TARGET = ex_ci20_cpm
241.8 +SRC_C = ci20_cpm.c
241.9 +REQUIRES_LIBS = libio l4re_c-util libdrivers-cpm
241.10 +
241.11 +include $(L4DIR)/mk/prog.mk
242.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
242.2 +++ b/pkg/landfall-examples/ci20_cpm/ci20_cpm.c Sun May 13 01:34:16 2018 +0200
242.3 @@ -0,0 +1,197 @@
242.4 +/*
242.5 + * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
242.6 + * economic rights: Technische Universität Dresden (Germany)
242.7 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
242.8 + *
242.9 + * This file is part of TUD:OS and distributed under the terms of the
242.10 + * GNU General Public License 2.
242.11 + * Please see the COPYING-GPL-2 file for details.
242.12 + */
242.13 +/*
242.14 + * Access the clock and power management unit on the MIPS Creator CI20 board.
242.15 + */
242.16 +
242.17 +#include <l4/devices/cpm-jz4780.h>
242.18 +#include <l4/io/io.h>
242.19 +#include <l4/re/env.h>
242.20 +#include <l4/re/c/util/cap_alloc.h>
242.21 +#include <l4/sys/factory.h>
242.22 +#include <l4/sys/icu.h>
242.23 +#include <l4/sys/ipc.h>
242.24 +#include <l4/sys/irq.h>
242.25 +#include <l4/vbus/vbus.h>
242.26 +#include <stdio.h>
242.27 +#include <unistd.h>
242.28 +#include <stdint.h>
242.29 +
242.30 +
242.31 +
242.32 +/* Device and resource discovery. */
242.33 +
242.34 +static char const *resource_type(enum l4io_resource_types_t type)
242.35 +{
242.36 + switch (type)
242.37 + {
242.38 + case L4VBUS_RESOURCE_INVALID:
242.39 + return "INVALID";
242.40 +
242.41 + case L4VBUS_RESOURCE_IRQ:
242.42 + return "IRQ";
242.43 +
242.44 + case L4VBUS_RESOURCE_MEM:
242.45 + return "MEMORY";
242.46 +
242.47 + default:
242.48 + return "OTHER";
242.49 + }
242.50 +}
242.51 +
242.52 +static int cpm_get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
242.53 +{
242.54 + int result = l4io_lookup_device(hid, dh, 0, rh);
242.55 +
242.56 + if (result < 0)
242.57 + printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");
242.58 +
242.59 + return result;
242.60 +}
242.61 +
242.62 +static int cpm_get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
242.63 + enum l4io_resource_types_t type)
242.64 +{
242.65 + int current = 0, result = 0;
242.66 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
242.67 +
242.68 + do
242.69 + {
242.70 + result = l4vbus_get_resource(vbus, dh, current, res);
242.71 +
242.72 + if (result)
242.73 + printf("Could not access resource of type %s.\n", resource_type(type));
242.74 + else
242.75 + printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,
242.76 + resource_type(res->type), res->start, res->end);
242.77 +
242.78 + current++;
242.79 + }
242.80 + while ((!result) && (res->type != type));
242.81 +
242.82 + return result;
242.83 +}
242.84 +
242.85 +static int cpm_get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
242.86 +{
242.87 + l4io_device_handle_t dh;
242.88 + l4io_resource_handle_t rh;
242.89 + l4io_resource_t res;
242.90 + int result;
242.91 +
242.92 + result = cpm_get_device(hid, &dh, &rh);
242.93 +
242.94 + if (result < 0)
242.95 + return result;
242.96 +
242.97 + result = cpm_get_resource(dh, &res, L4IO_RESOURCE_MEM);
242.98 +
242.99 + if (result)
242.100 + return result;
242.101 +
242.102 + if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,
242.103 + L4IO_MEM_NONCACHED, start)))
242.104 + {
242.105 + printf("Could not get address for '%s'.\n", hid);
242.106 + return result;
242.107 + }
242.108 +
242.109 + printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);
242.110 +
242.111 + *end = *start + (res.end - res.start + 1);
242.112 +
242.113 + return 0;
242.114 +}
242.115 +
242.116 +int main(void)
242.117 +{
242.118 + l4_addr_t cpm_base = 0, cpm_base_end = 0;
242.119 + void *cpm;
242.120 + int result = 0;
242.121 +
242.122 + /* Obtain resource details describing I/O memory. */
242.123 +
242.124 + printf("Access CPM...\n");
242.125 +
242.126 + if ((result = cpm_get_memory("jz4780-cpm", &cpm_base, &cpm_base_end)) < 0)
242.127 + return 1;
242.128 +
242.129 + printf("CPM at 0x%lx...0x%lx.\n", cpm_base, cpm_base_end);
242.130 +
242.131 + cpm = jz4780_cpm_init(cpm_base);
242.132 +
242.133 + /* Read information from the clock and power management unit. */
242.134 +
242.135 + printf("Main source: %d\n", jz4780_cpm_get_main_source(cpm));
242.136 + printf(" Main frequency: %d\n", jz4780_cpm_get_main_frequency(cpm));
242.137 + printf("APLL frequency: %d\n", jz4780_cpm_get_apll_frequency(cpm));
242.138 + printf("EPLL frequency: %d\n", jz4780_cpm_get_epll_frequency(cpm));
242.139 + printf("MPLL frequency: %d\n", jz4780_cpm_get_mpll_frequency(cpm));
242.140 + printf("VPLL frequency: %d\n", jz4780_cpm_get_vpll_frequency(cpm));
242.141 + printf("CPU divider: %d\n", jz4780_cpm_get_cpu_divider(cpm));
242.142 + printf(" CPU frequency: %d\n", jz4780_cpm_get_cpu_frequency(cpm));
242.143 + printf("Memory source: %d\n", jz4780_cpm_get_memory_source(cpm));
242.144 + printf(" Memory source frequency: %d\n", jz4780_cpm_get_memory_source_frequency(cpm));
242.145 + printf(" Memory divider: %d\n", jz4780_cpm_get_memory_divider(cpm));
242.146 + printf(" Memory frequency: %d\n", jz4780_cpm_get_memory_frequency(cpm));
242.147 + printf("APB source: %d\n", jz4780_cpm_get_pclock_source(cpm));
242.148 + printf(" APB source frequency: %d\n", jz4780_cpm_get_pclock_source_frequency(cpm));
242.149 + printf(" APB divider: %d\n", jz4780_cpm_get_pclock_divider(cpm));
242.150 + printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_pclock_frequency(cpm));
242.151 + printf("AHB0 source: %d\n", jz4780_cpm_get_hclock0_source(cpm));
242.152 + printf(" AHB0 source frequency: %d\n", jz4780_cpm_get_hclock0_source_frequency(cpm));
242.153 + printf(" AHB0 divider: %d\n", jz4780_cpm_get_hclock0_divider(cpm));
242.154 + printf(" Fast peripheral (AHB0) frequency: %d\n", jz4780_cpm_get_hclock0_frequency(cpm));
242.155 + printf("AHB2 source: %d\n", jz4780_cpm_get_hclock2_source(cpm));
242.156 + printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_hclock2_source_frequency(cpm));
242.157 + printf(" AHB2 divider: %d\n", jz4780_cpm_get_hclock2_divider(cpm));
242.158 + printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_hclock2_frequency(cpm));
242.159 + printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
242.160 + printf(" LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm));
242.161 + printf(" LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
242.162 + printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
242.163 +
242.164 + /* Attempt to set the pixel clock frequency. */
242.165 +
242.166 + jz4780_cpm_set_lcd_pixel_frequency(cpm, 108000000);
242.167 +
242.168 + printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm));
242.169 + printf(" LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm));
242.170 + printf(" LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm));
242.171 + printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_lcd_pixel_frequency(cpm));
242.172 +
242.173 + /* Attempt to set the peripheral clock frequency. */
242.174 +
242.175 + jz4780_cpm_set_pclock_source(cpm, 1);
242.176 +
242.177 + printf("APB source: %d\n", jz4780_cpm_get_pclock_source(cpm));
242.178 + printf(" APB source frequency: %d\n", jz4780_cpm_get_pclock_source_frequency(cpm));
242.179 + printf(" APB divider: %d\n", jz4780_cpm_get_pclock_divider(cpm));
242.180 + printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_pclock_frequency(cpm));
242.181 + printf("AHB2 source: %d\n", jz4780_cpm_get_hclock2_source(cpm));
242.182 + printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_hclock2_source_frequency(cpm));
242.183 + printf(" AHB2 divider: %d\n", jz4780_cpm_get_hclock2_divider(cpm));
242.184 + printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_hclock2_frequency(cpm));
242.185 +
242.186 + /* Attempt to set the MPLL output to EXCLK divided by 4. */
242.187 +
242.188 + jz4780_cpm_set_mpll_parameters(cpm, 1, 4, 1);
242.189 +
242.190 + printf("APB source: %d\n", jz4780_cpm_get_pclock_source(cpm));
242.191 + printf(" APB source frequency: %d\n", jz4780_cpm_get_pclock_source_frequency(cpm));
242.192 + printf(" APB divider: %d\n", jz4780_cpm_get_pclock_divider(cpm));
242.193 + printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_pclock_frequency(cpm));
242.194 + printf("AHB2 source: %d\n", jz4780_cpm_get_hclock2_source(cpm));
242.195 + printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_hclock2_source_frequency(cpm));
242.196 + printf(" AHB2 divider: %d\n", jz4780_cpm_get_hclock2_divider(cpm));
242.197 + printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_hclock2_frequency(cpm));
242.198 +
242.199 + return 0;
242.200 +}
243.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
243.2 +++ b/pkg/landfall-examples/ci20_i2c/Makefile Sun May 13 01:34:16 2018 +0200
243.3 @@ -0,0 +1,8 @@
243.4 +PKGDIR ?= ../..
243.5 +L4DIR ?= $(PKGDIR)/../..
243.6 +
243.7 +TARGET = ex_ci20_i2c
243.8 +SRC_C = ci20_i2c.c
243.9 +REQUIRES_LIBS = libio l4re_c-util libdrivers-i2c libdrivers-cpm libdrivers-gpio libedid
243.10 +
243.11 +include $(L4DIR)/mk/prog.mk
244.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
244.2 +++ b/pkg/landfall-examples/ci20_i2c/ci20_i2c.c Sun May 13 01:34:16 2018 +0200
244.3 @@ -0,0 +1,348 @@
244.4 +/*
244.5 + * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
244.6 + * economic rights: Technische Universität Dresden (Germany)
244.7 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
244.8 + *
244.9 + * This file is part of TUD:OS and distributed under the terms of the
244.10 + * GNU General Public License 2.
244.11 + * Please see the COPYING-GPL-2 file for details.
244.12 + */
244.13 +/*
244.14 + * Access the I2C peripherals on the MIPS Creator CI20 board.
244.15 + */
244.16 +
244.17 +#include <l4/devices/cpm-jz4780.h>
244.18 +#include <l4/devices/gpio-jz4780.h>
244.19 +#include <l4/devices/i2c-jz4780.h>
244.20 +#include <l4/io/io.h>
244.21 +#include <l4/libedid/edid.h>
244.22 +#include <l4/re/env.h>
244.23 +#include <l4/re/c/util/cap_alloc.h>
244.24 +#include <l4/sys/factory.h>
244.25 +#include <l4/sys/icu.h>
244.26 +#include <l4/sys/ipc.h>
244.27 +#include <l4/sys/irq.h>
244.28 +#include <l4/vbus/vbus.h>
244.29 +#include <stdio.h>
244.30 +#include <unistd.h>
244.31 +#include <stdint.h>
244.32 +
244.33 +
244.34 +
244.35 +enum {
244.36 + DDCSCL = 24, /* via PORTF */
244.37 + DDCSDA = 25, /* via PORTF */
244.38 +};
244.39 +
244.40 +
244.41 +
244.42 +/* Device and resource discovery. */
244.43 +
244.44 +static char const *resource_type(enum l4io_resource_types_t type)
244.45 +{
244.46 + switch (type)
244.47 + {
244.48 + case L4VBUS_RESOURCE_INVALID:
244.49 + return "INVALID";
244.50 +
244.51 + case L4VBUS_RESOURCE_IRQ:
244.52 + return "IRQ";
244.53 +
244.54 + case L4VBUS_RESOURCE_MEM:
244.55 + return "MEMORY";
244.56 +
244.57 + default:
244.58 + return "OTHER";
244.59 + }
244.60 +}
244.61 +
244.62 +static int vbus_get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
244.63 +{
244.64 + int result = l4io_lookup_device(hid, dh, 0, rh);
244.65 +
244.66 + if (result < 0)
244.67 + printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");
244.68 +
244.69 + return result;
244.70 +}
244.71 +
244.72 +static int vbus_get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
244.73 + enum l4io_resource_types_t type)
244.74 +{
244.75 + int current = 0, result = 0;
244.76 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
244.77 +
244.78 + do
244.79 + {
244.80 + result = l4vbus_get_resource(vbus, dh, current, res);
244.81 +
244.82 + if (result)
244.83 + printf("Could not access resource of type %s.\n", resource_type(type));
244.84 + else
244.85 + printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,
244.86 + resource_type(res->type), res->start, res->end);
244.87 +
244.88 + current++;
244.89 + }
244.90 + while ((!result) && (res->type != type));
244.91 +
244.92 + return result;
244.93 +}
244.94 +
244.95 +static int vbus_get_irq(char const *hid, l4_uint32_t *start, l4_uint32_t *end)
244.96 +{
244.97 + l4io_device_handle_t dh;
244.98 + l4io_resource_handle_t rh;
244.99 + l4io_resource_t res;
244.100 + int result;
244.101 +
244.102 + result = vbus_get_device(hid, &dh, &rh);
244.103 +
244.104 + if (result < 0)
244.105 + return result;
244.106 +
244.107 + result = vbus_get_resource(dh, &res, L4IO_RESOURCE_IRQ);
244.108 +
244.109 + if (result)
244.110 + return result;
244.111 +
244.112 + *start = res.start;
244.113 + *end = res.end;
244.114 +
244.115 + return result;
244.116 +}
244.117 +
244.118 +static int vbus_get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
244.119 +{
244.120 + l4io_device_handle_t dh;
244.121 + l4io_resource_handle_t rh;
244.122 + l4io_resource_t res;
244.123 + int result;
244.124 +
244.125 + result = vbus_get_device(hid, &dh, &rh);
244.126 +
244.127 + if (result < 0)
244.128 + return result;
244.129 +
244.130 + result = vbus_get_resource(dh, &res, L4IO_RESOURCE_MEM);
244.131 +
244.132 + if (result)
244.133 + return result;
244.134 +
244.135 + if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,
244.136 + L4IO_MEM_NONCACHED, start)))
244.137 + {
244.138 + printf("Could not get address for '%s'.\n", hid);
244.139 + return result;
244.140 + }
244.141 +
244.142 + printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);
244.143 +
244.144 + *end = *start + (res.end - res.start + 1);
244.145 +
244.146 + return 0;
244.147 +}
244.148 +
244.149 +static long item_in_range(long start, long end, long index)
244.150 +{
244.151 + if (start < end)
244.152 + return start + index;
244.153 + else
244.154 + return start - index;
244.155 +}
244.156 +
244.157 +static void show_deviceid(uint8_t buf[])
244.158 +{
244.159 + printf("Manufacturer %x part %x revision %x\n",
244.160 + (buf[0] << 4) | (buf[1] >> 4),
244.161 + ((buf[1] & 0xf) << 5) | (buf[2] >> 3),
244.162 + buf[2] & 0x7);
244.163 +}
244.164 +
244.165 +static void show_data(uint8_t buf[], unsigned pos)
244.166 +{
244.167 + unsigned i;
244.168 +
244.169 + if (pos)
244.170 + {
244.171 + printf("Read %d bytes from bus.\n", pos);
244.172 + for (i = 0; i < pos; i++)
244.173 + printf(" %02x", buf[i]);
244.174 + printf("\n");
244.175 + }
244.176 + else
244.177 + printf("No reply from bus.\n");
244.178 +}
244.179 +
244.180 +int main(void)
244.181 +{
244.182 + l4_addr_t gpio_base = 0, gpio_base_end = 0;
244.183 + l4_addr_t port_f, port_f_end;
244.184 + l4_addr_t i2c_base = 0, i2c_base_end = 0, cpm_base = 0, cpm_base_end;
244.185 + void *gpio_port_f;
244.186 + void *i2c, *i2c_channel, *cpm;
244.187 + l4_uint32_t i2c_irq_start = 0, i2c_irq_end = 0, i2c_irq;
244.188 + l4_cap_idx_t irqcap, icucap;
244.189 + l4_msgtag_t tag;
244.190 + long err;
244.191 + int result = 0;
244.192 + uint8_t buf[256];
244.193 + unsigned pos;
244.194 + unsigned width = 0, height = 0;
244.195 +
244.196 + /* Obtain capabilities for the interrupt controller and an interrupt. */
244.197 +
244.198 + irqcap = l4re_util_cap_alloc();
244.199 + icucap = l4re_env_get_cap("icu");
244.200 +
244.201 + if (l4_is_invalid_cap(icucap))
244.202 + {
244.203 + printf("No 'icu' capability available in the virtual bus.\n");
244.204 + return 1;
244.205 + }
244.206 +
244.207 + if (l4_is_invalid_cap(irqcap))
244.208 + {
244.209 + printf("No capability available for the interrupt.\n");
244.210 + return 1;
244.211 + }
244.212 +
244.213 + /* Obtain resource details describing the interrupt for I2C channel 4. */
244.214 +
244.215 + printf("Access IRQ...\n");
244.216 +
244.217 + if ((result = vbus_get_irq("jz4780-i2c", &i2c_irq_start, &i2c_irq_end)) < 0)
244.218 + return 1;
244.219 +
244.220 + i2c_irq = item_in_range(i2c_irq_start, i2c_irq_end, 4);
244.221 + printf("IRQ range at %d...%d.\n", i2c_irq_start, i2c_irq_end);
244.222 + printf("I2C IRQ at %d.\n", i2c_irq);
244.223 +
244.224 + /* Obtain resource details describing I/O memory. */
244.225 +
244.226 + printf("Access GPIO...\n");
244.227 +
244.228 + if ((result = vbus_get_memory("jz4780-gpio", &gpio_base, &gpio_base_end)) < 0)
244.229 + return 1;
244.230 +
244.231 + printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end);
244.232 +
244.233 + printf("Access CPM...\n");
244.234 +
244.235 + if ((result = vbus_get_memory("jz4780-cpm", &cpm_base, &cpm_base_end)) < 0)
244.236 + return 1;
244.237 +
244.238 + printf("CPM at 0x%lx...0x%lx.\n", cpm_base, cpm_base_end);
244.239 +
244.240 + printf("Access I2C...\n");
244.241 +
244.242 + if ((result = vbus_get_memory("jz4780-i2c", &i2c_base, &i2c_base_end)) < 0)
244.243 + return 1;
244.244 +
244.245 + printf("I2C at 0x%lx...0x%lx.\n", i2c_base, i2c_base_end);
244.246 +
244.247 + /* Create an interrupt object. */
244.248 +
244.249 + if ((err = l4_error(tag = l4_factory_create_irq(l4re_global_env->factory, irqcap))))
244.250 + {
244.251 + printf("Could not create IRQ object: %lx\n", err);
244.252 + return 1;
244.253 + }
244.254 +
244.255 + /* Bind the interrupt object to the IRQ number. */
244.256 +
244.257 + if ((err = l4_error(l4_icu_bind(icucap, i2c_irq, irqcap))))
244.258 + {
244.259 + printf("Could not bind IRQ %d to the ICU: %ld\n", i2c_irq, err);
244.260 + return 1;
244.261 + }
244.262 +
244.263 + /* Attach ourselves to the interrupt handler. */
244.264 +
244.265 + tag = l4_irq_attach(irqcap, 0xDEAD, l4re_env()->main_thread);
244.266 +
244.267 + if ((err = l4_error(tag)))
244.268 + {
244.269 + printf("Could not attach to IRQ %d: %ld\n", i2c_irq, err);
244.270 + return 1;
244.271 + }
244.272 +
244.273 + /* Configure pins. */
244.274 +
244.275 + port_f = gpio_base + 0x500;
244.276 + port_f_end = port_f + 0x100;
244.277 +
244.278 + printf("PORTF at 0x%lx...0x%lx.\n", port_f, port_f_end);
244.279 +
244.280 + gpio_port_f = jz4780_gpio_init(port_f, port_f_end, 32, 0xffa7f00f, 0x00580ff0);
244.281 +
244.282 + printf("Set up GPIO pins...\n");
244.283 +
244.284 + jz4780_gpio_config_pad(gpio_port_f, DDCSCL, Function_alt, 1);
244.285 + jz4780_gpio_config_pad(gpio_port_f, DDCSDA, Function_alt, 1);
244.286 +
244.287 + /* Obtain CPM and I2C objects. */
244.288 +
244.289 + cpm = jz4780_cpm_init(cpm_base);
244.290 +
244.291 + /* Attempt to set the PCLK source to SCLK_A. */
244.292 +
244.293 + jz4780_cpm_set_pclock_source(cpm, 1);
244.294 + printf("Peripheral clock: %d\n", jz4780_cpm_get_pclock_frequency(cpm));
244.295 +
244.296 + /* Obtain I2C reference. */
244.297 +
244.298 + i2c = jz4780_i2c_init(i2c_base, i2c_base_end, cpm, 100000); /* 100 kHz */
244.299 +
244.300 + printf("Trying DDC on I2C4...\n");
244.301 +
244.302 + i2c_channel = jz4780_i2c_get_channel(i2c, 4);
244.303 +
244.304 + /* Attempt to read from address 0x50 for DDC.
244.305 + See: drivers/video/fbdev/core/fb_ddc.c */
244.306 +
244.307 + jz4780_i2c_set_target(i2c_channel, 0x50);
244.308 + buf[0] = 0;
244.309 + jz4780_i2c_write(i2c_channel, buf, 1);
244.310 + jz4780_i2c_start_read(i2c_channel, buf, 128);
244.311 +
244.312 + printf("Waiting\n");
244.313 +
244.314 + while (!jz4780_i2c_read_done(i2c_channel))
244.315 + {
244.316 + if (jz4780_i2c_read_incomplete(i2c_channel))
244.317 + {
244.318 + printf("Failed\n");
244.319 + break;
244.320 + }
244.321 +
244.322 + tag = l4_irq_receive(irqcap, L4_IPC_NEVER);
244.323 +
244.324 + if ((err = l4_ipc_error(tag, l4_utcb())))
244.325 + {
244.326 + printf("Error on IRQ receive: %ld\n", err);
244.327 + continue;
244.328 + }
244.329 +
244.330 + jz4780_i2c_read(i2c_channel);
244.331 + }
244.332 +
244.333 + pos = jz4780_i2c_have_read(i2c_channel);
244.334 + show_data(buf, pos);
244.335 +
244.336 + /* Attempt to decode EDID information. */
244.337 +
244.338 + libedid_prefered_resolution(buf, &width, &height);
244.339 + printf("Preferred resolution: %d x %d\n", width, height);
244.340 +
244.341 + libedid_dump_standard_timings(buf);
244.342 +
244.343 + /* Detach from the interrupt. */
244.344 +
244.345 + tag = l4_irq_detach(irqcap);
244.346 +
244.347 + if ((err = l4_error(tag)))
244.348 + printf("Error detaching from IRQ: %ld\n", err);
244.349 +
244.350 + return 0;
244.351 +}
245.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
245.2 +++ b/pkg/landfall-examples/ci20_leds/Makefile Sun May 13 01:34:16 2018 +0200
245.3 @@ -0,0 +1,8 @@
245.4 +PKGDIR ?= ../..
245.5 +L4DIR ?= $(PKGDIR)/../..
245.6 +
245.7 +TARGET = ex_ci20_leds
245.8 +SRC_C = ci20_leds.c
245.9 +REQUIRES_LIBS = libio l4re_c-util libdrivers-gpio
245.10 +
245.11 +include $(L4DIR)/mk/prog.mk
246.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
246.2 +++ b/pkg/landfall-examples/ci20_leds/ci20_leds.c Sun May 13 01:34:16 2018 +0200
246.3 @@ -0,0 +1,275 @@
246.4 +/*
246.5 + * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
246.6 + * economic rights: Technische Universität Dresden (Germany)
246.7 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
246.8 + *
246.9 + * This file is part of TUD:OS and distributed under the terms of the
246.10 + * GNU General Public License 2.
246.11 + * Please see the COPYING-GPL-2 file for details.
246.12 + */
246.13 +/*
246.14 + * Access the LED and other GPIOs on the MIPS Creator CI20 board.
246.15 + * This example shows how to use the following GPIOs:
246.16 + *
246.17 + * PD17 - SW1 button
246.18 + * PF15 - blue/red LED (high -> red, low -> blue)
246.19 + */
246.20 +
246.21 +#include <l4/devices/gpio-jz4780.h>
246.22 +#include <l4/io/io.h>
246.23 +#include <l4/re/env.h>
246.24 +#include <l4/re/c/util/cap_alloc.h>
246.25 +#include <l4/sys/factory.h>
246.26 +#include <l4/sys/icu.h>
246.27 +#include <l4/sys/ipc.h>
246.28 +#include <l4/sys/irq.h>
246.29 +#include <l4/vbus/vbus.h>
246.30 +#include <stdio.h>
246.31 +#include <unistd.h>
246.32 +#include <stdint.h>
246.33 +
246.34 +enum {
246.35 + LED = 15, // via PORTF
246.36 + SW1 = 17, // via PORTD
246.37 +};
246.38 +
246.39 +
246.40 +
246.41 +/* Device and resource discovery. */
246.42 +
246.43 +static char const *resource_type(enum l4io_resource_types_t type)
246.44 +{
246.45 + switch (type)
246.46 + {
246.47 + case L4VBUS_RESOURCE_INVALID:
246.48 + return "INVALID";
246.49 +
246.50 + case L4VBUS_RESOURCE_IRQ:
246.51 + return "IRQ";
246.52 +
246.53 + case L4VBUS_RESOURCE_MEM:
246.54 + return "MEMORY";
246.55 +
246.56 + default:
246.57 + return "OTHER";
246.58 + }
246.59 +}
246.60 +
246.61 +static int gpio_get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
246.62 +{
246.63 + int result = l4io_lookup_device(hid, dh, 0, rh);
246.64 +
246.65 + if (result < 0)
246.66 + printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");
246.67 +
246.68 + return result;
246.69 +}
246.70 +
246.71 +static int gpio_get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
246.72 + enum l4io_resource_types_t type)
246.73 +{
246.74 + int current = 0, result = 0;
246.75 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
246.76 +
246.77 + do
246.78 + {
246.79 + result = l4vbus_get_resource(vbus, dh, current, res);
246.80 +
246.81 + if (result)
246.82 + printf("Could not access resource of type %s.\n", resource_type(type));
246.83 + else
246.84 + printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,
246.85 + resource_type(res->type), res->start, res->end);
246.86 +
246.87 + current++;
246.88 + }
246.89 + while ((!result) && (res->type != type));
246.90 +
246.91 + return result;
246.92 +}
246.93 +
246.94 +static int gpio_get_irq(char const *hid, l4_uint32_t *start, l4_uint32_t *end)
246.95 +{
246.96 + l4io_device_handle_t dh;
246.97 + l4io_resource_handle_t rh;
246.98 + l4io_resource_t res;
246.99 + int result;
246.100 +
246.101 + result = gpio_get_device(hid, &dh, &rh);
246.102 +
246.103 + if (result < 0)
246.104 + return result;
246.105 +
246.106 + result = gpio_get_resource(dh, &res, L4IO_RESOURCE_IRQ);
246.107 +
246.108 + if (result)
246.109 + return result;
246.110 +
246.111 + *start = res.start;
246.112 + *end = res.end;
246.113 +
246.114 + return result;
246.115 +}
246.116 +
246.117 +static int gpio_get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
246.118 +{
246.119 + l4io_device_handle_t dh;
246.120 + l4io_resource_handle_t rh;
246.121 + l4io_resource_t res;
246.122 + int result;
246.123 +
246.124 + result = gpio_get_device(hid, &dh, &rh);
246.125 +
246.126 + if (result < 0)
246.127 + return result;
246.128 +
246.129 + result = gpio_get_resource(dh, &res, L4IO_RESOURCE_MEM);
246.130 +
246.131 + if (result)
246.132 + return result;
246.133 +
246.134 + if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,
246.135 + L4IO_MEM_NONCACHED, start)))
246.136 + {
246.137 + printf("Could not get address for '%s'.\n", hid);
246.138 + return result;
246.139 + }
246.140 +
246.141 + printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);
246.142 +
246.143 + *end = *start + (res.end - res.start + 1);
246.144 +
246.145 + return 0;
246.146 +}
246.147 +
246.148 +static long item_in_range(long start, long end, long index)
246.149 +{
246.150 + if (start < end)
246.151 + return start + index;
246.152 + else
246.153 + return start - index;
246.154 +}
246.155 +
246.156 +int main(void)
246.157 +{
246.158 + l4_addr_t gpio_base = 0, gpio_base_end = 0, port_d, port_d_end, port_f, port_f_end;
246.159 + l4_uint32_t gpio_irq_start = 0, gpio_irq_end = 0, gpio_irq;
246.160 + l4_cap_idx_t irqcap, icucap;
246.161 + l4_msgtag_t tag;
246.162 + long err;
246.163 + void *gpio_port_d, *gpio_port_f, *gpio_irq_pin;
246.164 + int result = 0;
246.165 + int led = 0;
246.166 +
246.167 + /* Obtain capabilities for the interrupt controller and an interrupt. */
246.168 +
246.169 + irqcap = l4re_util_cap_alloc();
246.170 + icucap = l4re_env_get_cap("icu");
246.171 +
246.172 + if (l4_is_invalid_cap(icucap))
246.173 + {
246.174 + printf("No 'icu' capability available in the virtual bus.\n");
246.175 + return 1;
246.176 + }
246.177 +
246.178 + if (l4_is_invalid_cap(irqcap))
246.179 + {
246.180 + printf("No capability available for the interrupt.\n");
246.181 + return 1;
246.182 + }
246.183 +
246.184 + /* Obtain resource details describing the interrupt and I/O memory. */
246.185 +
246.186 + printf("Access IRQ...\n");
246.187 +
246.188 + if ((result = gpio_get_irq("jz4780-gpio", &gpio_irq_start, &gpio_irq_end)) < 0)
246.189 + return 1;
246.190 +
246.191 + gpio_irq = item_in_range(gpio_irq_start, gpio_irq_end, 3);
246.192 + printf("IRQ range at %d...%d.\n", gpio_irq_start, gpio_irq_end);
246.193 + printf("PORTD IRQ at %d.\n", gpio_irq);
246.194 +
246.195 + printf("Access GPIO...\n");
246.196 +
246.197 + if ((result = gpio_get_memory("jz4780-gpio", &gpio_base, &gpio_base_end)) < 0)
246.198 + return 1;
246.199 +
246.200 + port_d = gpio_base + 0x300;
246.201 + port_d_end = port_d + 0x100;
246.202 + port_f = gpio_base + 0x500;
246.203 + port_f_end = port_f + 0x100;
246.204 +
246.205 + printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end);
246.206 + printf("PORTD at 0x%lx...0x%lx.\n", port_d, port_d_end);
246.207 + printf("PORTF at 0x%lx...0x%lx.\n", port_f, port_f_end);
246.208 +
246.209 + gpio_port_d = jz4780_gpio_init(port_d, port_d_end, 32, 0xffff4fff, 0x0000b000);
246.210 + gpio_port_f = jz4780_gpio_init(port_f, port_f_end, 32, 0xffa7f00f, 0x00580ff0);
246.211 +
246.212 + /* Create an interrupt object. */
246.213 +
246.214 + if ((err = l4_error(tag = l4_factory_create_irq(l4re_global_env->factory, irqcap))))
246.215 + {
246.216 + printf("Could not create IRQ object: %lx\n", err);
246.217 + return 1;
246.218 + }
246.219 +
246.220 + /* Bind the interrupt object to the IRQ number. */
246.221 +
246.222 + if ((err = l4_error(l4_icu_bind(icucap, gpio_irq, irqcap))))
246.223 + {
246.224 + printf("Could not bind IRQ %d to the ICU: %ld\n", gpio_irq, err);
246.225 + return 1;
246.226 + }
246.227 +
246.228 + /* Attach ourselves to the interrupt handler. */
246.229 +
246.230 + tag = l4_irq_attach(irqcap, 0xDEAD, l4re_env()->main_thread);
246.231 +
246.232 + if ((err = l4_error(tag)))
246.233 + {
246.234 + printf("Could not attach to IRQ %d: %ld\n", gpio_irq, err);
246.235 + return 1;
246.236 + }
246.237 +
246.238 + /* Set the GPIO pins up. */
246.239 +
246.240 + printf("Set up GPIO pins...\n");
246.241 +
246.242 + jz4780_gpio_setup(gpio_port_d, SW1, L4VBUS_GPIO_SETUP_IRQ, 1);
246.243 + jz4780_gpio_setup(gpio_port_f, LED, L4VBUS_GPIO_SETUP_OUTPUT, 0);
246.244 +
246.245 + gpio_irq_pin = jz4780_gpio_get_irq(gpio_port_d, SW1);
246.246 + jz4780_gpio_irq_set_mode(gpio_irq_pin, L4_IRQ_F_LEVEL_HIGH);
246.247 +
246.248 + printf("Press SW1 to invert LED.\n");
246.249 +
246.250 + while (1)
246.251 + {
246.252 + tag = l4_irq_receive(irqcap, L4_IPC_NEVER);
246.253 +
246.254 + if ((err = l4_ipc_error(tag, l4_utcb())))
246.255 + {
246.256 + printf("Error on IRQ receive: %ld\n", err);
246.257 + continue;
246.258 + }
246.259 +
246.260 + printf("SW1: %x\n", jz4780_gpio_get(gpio_port_d, SW1));
246.261 +
246.262 + if (jz4780_gpio_get(gpio_port_d, SW1))
246.263 + {
246.264 + printf("Invert LED\n");
246.265 + jz4780_gpio_set(gpio_port_f, LED, led);
246.266 + led = 1 - led;
246.267 + }
246.268 + }
246.269 +
246.270 + /* Detach from the interrupt. */
246.271 +
246.272 + tag = l4_irq_detach(irqcap);
246.273 +
246.274 + if ((err = l4_error(tag)))
246.275 + printf("Error detaching from IRQ: %ld\n", err);
246.276 +
246.277 + return 0;
246.278 +}
247.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
247.2 +++ b/pkg/landfall-examples/jz4740_lcd_driver/Makefile Sun May 13 01:34:16 2018 +0200
247.3 @@ -0,0 +1,8 @@
247.4 +PKGDIR ?= ../..
247.5 +L4DIR ?= $(PKGDIR)/../..
247.6 +
247.7 +TARGET = ex_jz4740_lcd_driver
247.8 +SRC_C = jz4740_lcd_driver.c
247.9 +REQUIRES_LIBS = libdevice-lcd-jz4740
247.10 +
247.11 +include $(L4DIR)/mk/prog.mk
248.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
248.2 +++ b/pkg/landfall-examples/jz4740_lcd_driver/jz4740_lcd_driver.c Sun May 13 01:34:16 2018 +0200
248.3 @@ -0,0 +1,84 @@
248.4 +/*
248.5 + * Access the LCD on JZ4740-based platforms.
248.6 + *
248.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
248.8 + *
248.9 + * This program is free software; you can redistribute it and/or
248.10 + * modify it under the terms of the GNU General Public License as
248.11 + * published by the Free Software Foundation; either version 2 of
248.12 + * the License, or (at your option) any later version.
248.13 + *
248.14 + * This program is distributed in the hope that it will be useful,
248.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
248.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
248.17 + * GNU General Public License for more details.
248.18 + *
248.19 + * You should have received a copy of the GNU General Public License
248.20 + * along with this program; if not, write to the Free Software
248.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
248.22 + * Boston, MA 02110-1301, USA
248.23 + */
248.24 +
248.25 +#include <l4/devices/lcd-device.h>
248.26 +#include <l4/re/c/video/view.h>
248.27 +#include <l4/sys/cache.h>
248.28 +
248.29 +#include <stdint.h>
248.30 +
248.31 +int main(void)
248.32 +{
248.33 + l4re_video_view_info_t view_info;
248.34 + l4_size_t i, limit, line, digit, row, mask, value, onpix, offpix;
248.35 +
248.36 + /* Obtain device and get framebuffer details. */
248.37 +
248.38 + void *lcd_device = lcd_get_device();
248.39 + l4_addr_t fb_vaddr = lcd_get_framebuffer(lcd_device);
248.40 + l4_size_t fb_size = lcd_get_framebuffer_size(lcd_device);
248.41 + uint32_t *fb32 = (uint32_t *) fb_vaddr;
248.42 + uint16_t *fb16 = (uint16_t *) fb_vaddr;
248.43 +
248.44 + if (!fb_vaddr) return 1;
248.45 +
248.46 + lcd_get_view_info(lcd_device, &view_info);
248.47 + lcd_enable(lcd_device);
248.48 +
248.49 + /* Try and show some values. */
248.50 +
248.51 + onpix = 0xffaaffaa; offpix = 0x11551155;
248.52 + mask = 0x80000000; value = (l4_size_t) view_info.width;
248.53 +
248.54 + i = 0;
248.55 + limit = fb_size / view_info.pixel_info.bytes_per_pixel;
248.56 + line = limit / view_info.height;
248.57 + digit = line / 32;
248.58 + row = line * 10;
248.59 +
248.60 + while (i < limit)
248.61 + {
248.62 + if (view_info.pixel_info.bytes_per_pixel == 2)
248.63 + fb16[i] = value & mask ? onpix : offpix;
248.64 + else
248.65 + fb32[i] = value & mask ? onpix : offpix;
248.66 +
248.67 + i++;
248.68 +
248.69 + if ((i % digit) == 0)
248.70 + {
248.71 + if (mask == 1) mask = 0x80000000;
248.72 + else mask >>= 1;
248.73 +
248.74 + onpix = (onpix >> 8) | ((onpix & 0xff) << 24);
248.75 + offpix = (offpix >> 8) | ((offpix & 0xff) << 24);
248.76 +
248.77 + if (i == row) value = (l4_size_t) view_info.height;
248.78 + else if (i == (row * 2)) value = 0x80000001;
248.79 + }
248.80 + }
248.81 +
248.82 + l4_cache_clean_data((unsigned long) fb_vaddr, (unsigned long) fb_vaddr + fb_size);
248.83 +
248.84 + while (1);
248.85 +
248.86 + return 0;
248.87 +}
249.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
249.2 +++ b/pkg/landfall-examples/keypad_ds_client/Makefile Sun May 13 01:34:16 2018 +0200
249.3 @@ -0,0 +1,10 @@
249.4 +PKGDIR ?= ../..
249.5 +L4DIR ?= $(PKGDIR)/../..
249.6 +
249.7 +TARGET = ex_keypad_ds_client
249.8 +#SRC_CC = keypad_ds_client.cc
249.9 +#REQUIRES_LIBS = l4re_c-util libdevice-keypad-client
249.10 +SRC_C = keypad_ds_client_c.c
249.11 +REQUIRES_LIBS = l4re_c-util libdevice-keypad-ops
249.12 +
249.13 +include $(L4DIR)/mk/prog.mk
250.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
250.2 +++ b/pkg/landfall-examples/keypad_ds_client/keypad_ds_client.cc Sun May 13 01:34:16 2018 +0200
250.3 @@ -0,0 +1,170 @@
250.4 +/*
250.5 + * Display the keypad matrix using the specified dimensions.
250.6 + *
250.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
250.8 + *
250.9 + * This program is free software; you can redistribute it and/or
250.10 + * modify it under the terms of the GNU General Public License as
250.11 + * published by the Free Software Foundation; either version 2 of
250.12 + * the License, or (at your option) any later version.
250.13 + *
250.14 + * This program is distributed in the hope that it will be useful,
250.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
250.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
250.17 + * GNU General Public License for more details.
250.18 + *
250.19 + * You should have received a copy of the GNU General Public License
250.20 + * along with this program; if not, write to the Free Software
250.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
250.22 + * Boston, MA 02110-1301, USA
250.23 + */
250.24 +
250.25 +#include <l4/devices/keypad-client.h>
250.26 +
250.27 +#include <l4/cxx/ipc_server>
250.28 +#include <l4/re/dataspace>
250.29 +#include <l4/re/env>
250.30 +#include <l4/re/rm>
250.31 +#include <l4/re/util/cap_alloc>
250.32 +
250.33 +#include <l4/re/c/util/video/goos_fb.h>
250.34 +#include <l4/re/c/video/view.h>
250.35 +
250.36 +#include <l4/util/util.h>
250.37 +#include <stdio.h>
250.38 +#include <unistd.h>
250.39 +#include <stdint.h>
250.40 +#include <stdlib.h>
250.41 +
250.42 +/* Video abstractions. */
250.43 +
250.44 +static l4re_util_video_goos_fb_t gfb;
250.45 +static l4re_video_view_info_t fbi;
250.46 +static void *fb;
250.47 +
250.48 +/* Keypad status and dimensions. */
250.49 +
250.50 +uint32_t *keypad = 0;
250.51 +void *keymem = 0;
250.52 +int columns, rows;
250.53 +
250.54 +
250.55 +
250.56 +static uint32_t bitmask(uint32_t size)
250.57 +{
250.58 + return (1 << size) - 1;
250.59 +}
250.60 +
250.61 +static uint32_t truncate_channel(uint32_t value, uint32_t size)
250.62 +{
250.63 + return (value >> (8 - size)) & bitmask(size);
250.64 +}
250.65 +
250.66 +static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value)
250.67 +{
250.68 + if (bpp <= 8) *(uint8_t *) pos = value;
250.69 + else if (bpp <= 16) *(uint16_t *) pos = value;
250.70 + else *(uint32_t *) pos = value;
250.71 +}
250.72 +
250.73 +/* Show the state of a key on the display. */
250.74 +
250.75 +static void show_keystate(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb)
250.76 +{
250.77 + uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
250.78 + uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel;
250.79 + uint32_t bytes_per_line = fbi.bytes_per_line;
250.80 + uint32_t pos;
250.81 + uint32_t col, row;
250.82 +
250.83 + rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) |
250.84 + (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) |
250.85 + (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift);
250.86 +
250.87 + for (row = 0; row < h; row++)
250.88 + {
250.89 + pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel;
250.90 +
250.91 + for (col = 0; col < w; col++)
250.92 + {
250.93 + set_pixel(pos, bpp, rgb);
250.94 + pos += bytes_per_pixel;
250.95 + }
250.96 + }
250.97 +}
250.98 +
250.99 +/* Show the keypad status on the display. */
250.100 +
250.101 +static void show_keypad(void)
250.102 +{
250.103 + uint32_t colsize = fbi.width / columns,
250.104 + rowsize = fbi.height / rows;
250.105 + uint8_t column, row;
250.106 + uint32_t mask;
250.107 +
250.108 + for (column = 0; column < columns; column++)
250.109 +
250.110 + for (row = 0, mask = 1 << (rows - 1);
250.111 + row < rows;
250.112 + row++, mask >>= 1)
250.113 +
250.114 + show_keystate(column * colsize, row * rowsize, colsize, rowsize,
250.115 + keypad[column] & mask ? 0xffffff : 0);
250.116 +
250.117 + /* Refresh the display. */
250.118 +
250.119 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height);
250.120 +}
250.121 +
250.122 +
250.123 +
250.124 +int main(int argc, char *argv[])
250.125 +{
250.126 + L4::Cap<Keypad_device_interface> keypad_server;
250.127 + L4::Cap<L4Re::Dataspace> mem;
250.128 +
250.129 + /* Obtain the keypad matrix dimensions. */
250.130 +
250.131 + if (argc < 3)
250.132 + return 1;
250.133 +
250.134 + columns = atoi(argv[1]);
250.135 + rows = atoi(argv[2]);
250.136 +
250.137 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
250.138 + return 1;
250.139 +
250.140 + if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
250.141 + return 1;
250.142 +
250.143 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
250.144 + return 1;
250.145 +
250.146 + /* Obtain a reference to the keypad. */
250.147 +
250.148 + keypad_server = L4Re::Env::env()->get_cap<Keypad_device_interface>("keypad");
250.149 + if (!keypad_server.is_valid()) return 1;
250.150 +
250.151 + /* Obtain a capability for the keypad data. */
250.152 +
250.153 + mem = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
250.154 + if (!mem.is_valid()) return 1;
250.155 +
250.156 + /* Obtain a reference to the keypad data. */
250.157 +
250.158 + if (keypad_server->get_keypad_data(mem)) return 1;
250.159 +
250.160 + /* Attach the keypad data to a region in this task. */
250.161 +
250.162 + if (L4Re::Env::env()->rm()->attach(&keymem, mem->size(), L4Re::Rm::Search_addr,
250.163 + L4::Ipc::make_cap_rw(mem)))
250.164 + return 1;
250.165 +
250.166 + /* Show the keypad state. */
250.167 +
250.168 + keypad = (uint32_t *) keymem;
250.169 +
250.170 + while (1) show_keypad();
250.171 +
250.172 + return 0;
250.173 +}
251.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
251.2 +++ b/pkg/landfall-examples/keypad_ds_client/keypad_ds_client_c.c Sun May 13 01:34:16 2018 +0200
251.3 @@ -0,0 +1,178 @@
251.4 +/*
251.5 + * Display the keypad matrix using the specified dimensions.
251.6 + *
251.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
251.8 + *
251.9 + * This program is free software; you can redistribute it and/or
251.10 + * modify it under the terms of the GNU General Public License as
251.11 + * published by the Free Software Foundation; either version 2 of
251.12 + * the License, or (at your option) any later version.
251.13 + *
251.14 + * This program is distributed in the hope that it will be useful,
251.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
251.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
251.17 + * GNU General Public License for more details.
251.18 + *
251.19 + * You should have received a copy of the GNU General Public License
251.20 + * along with this program; if not, write to the Free Software
251.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
251.22 + * Boston, MA 02110-1301, USA
251.23 + */
251.24 +
251.25 +#include <l4/devices/keypad-ops.h>
251.26 +
251.27 +#include <l4/re/c/rm.h>
251.28 +#include <l4/re/c/util/cap_alloc.h>
251.29 +#include <l4/re/env.h>
251.30 +#include <l4/util/util.h>
251.31 +#include <l4/sys/ipc.h>
251.32 +
251.33 +#include <l4/re/c/util/video/goos_fb.h>
251.34 +#include <l4/re/c/video/view.h>
251.35 +
251.36 +#include <l4/util/util.h>
251.37 +#include <stdio.h>
251.38 +#include <unistd.h>
251.39 +#include <stdint.h>
251.40 +#include <stdlib.h>
251.41 +
251.42 +/* Video abstractions. */
251.43 +
251.44 +static l4re_util_video_goos_fb_t gfb;
251.45 +static l4re_video_view_info_t fbi;
251.46 +static void *fb;
251.47 +
251.48 +/* Keypad status and dimensions. */
251.49 +
251.50 +uint32_t *keypad = 0;
251.51 +void *keymem = 0;
251.52 +int columns, rows;
251.53 +
251.54 +
251.55 +
251.56 +static uint32_t bitmask(uint32_t size)
251.57 +{
251.58 + return (1 << size) - 1;
251.59 +}
251.60 +
251.61 +static uint32_t truncate_channel(uint32_t value, uint32_t size)
251.62 +{
251.63 + return (value >> (8 - size)) & bitmask(size);
251.64 +}
251.65 +
251.66 +static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value)
251.67 +{
251.68 + if (bpp <= 8) *(uint8_t *) pos = value;
251.69 + else if (bpp <= 16) *(uint16_t *) pos = value;
251.70 + else *(uint32_t *) pos = value;
251.71 +}
251.72 +
251.73 +/* Show the state of a key on the display. */
251.74 +
251.75 +static void show_keystate(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb)
251.76 +{
251.77 + uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
251.78 + uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel;
251.79 + uint32_t bytes_per_line = fbi.bytes_per_line;
251.80 + uint32_t pos;
251.81 + uint32_t col, row;
251.82 +
251.83 + rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) |
251.84 + (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) |
251.85 + (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift);
251.86 +
251.87 + for (row = 0; row < h; row++)
251.88 + {
251.89 + pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel;
251.90 +
251.91 + for (col = 0; col < w; col++)
251.92 + {
251.93 + set_pixel(pos, bpp, rgb);
251.94 + pos += bytes_per_pixel;
251.95 + }
251.96 + }
251.97 +}
251.98 +
251.99 +/* Show the keypad status on the display. */
251.100 +
251.101 +static void show_keypad(void)
251.102 +{
251.103 + uint32_t colsize = fbi.width / columns,
251.104 + rowsize = fbi.height / rows;
251.105 + uint8_t column, row;
251.106 + uint32_t mask;
251.107 +
251.108 + for (column = 0; column < columns; column++)
251.109 +
251.110 + for (row = 0, mask = 1 << (rows - 1);
251.111 + row < rows;
251.112 + row++, mask >>= 1)
251.113 +
251.114 + show_keystate(column * colsize, row * rowsize, colsize, rowsize,
251.115 + keypad[column] & mask ? 0xffffff : 0);
251.116 +
251.117 + /* Refresh the display. */
251.118 +
251.119 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height);
251.120 +}
251.121 +
251.122 +
251.123 +
251.124 +int main(int argc, char *argv[])
251.125 +{
251.126 + l4_cap_idx_t keypad_server;
251.127 + l4re_ds_t mem;
251.128 + l4_msgtag_t tag;
251.129 +
251.130 + /* Obtain the keypad matrix dimensions. */
251.131 +
251.132 + if (argc < 3)
251.133 + return 1;
251.134 +
251.135 + columns = atoi(argv[1]);
251.136 + rows = atoi(argv[2]);
251.137 +
251.138 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
251.139 + return 1;
251.140 +
251.141 + if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
251.142 + return 1;
251.143 +
251.144 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
251.145 + return 1;
251.146 +
251.147 + /* Obtain a reference to the keypad. */
251.148 +
251.149 + keypad_server = l4re_env_get_cap("keypad");
251.150 + if (l4_is_invalid_cap(keypad_server)) return 1;
251.151 +
251.152 + /* Obtain a capability for the keypad data. */
251.153 +
251.154 + mem = l4re_util_cap_alloc();
251.155 + if (l4_is_invalid_cap(mem)) return 1;
251.156 +
251.157 + /* Obtain a reference to the keypad data. */
251.158 +
251.159 + l4_utcb_br()->bdr = 0;
251.160 + l4_utcb_br()->br[0] = L4_RCV_ITEM_SINGLE_CAP | mem;
251.161 +
251.162 + tag = l4_ipc_call(keypad_server, l4_utcb(),
251.163 + l4_msgtag(Keypad_op_get_keypad_data, 0, 0, 0), /* zero words, zero *sent* items */
251.164 + L4_IPC_NEVER);
251.165 +
251.166 + if (l4_ipc_error(tag, l4_utcb())) return 1;
251.167 +
251.168 + /* Attach the keypad data to a region in this task. */
251.169 +
251.170 + if (l4re_rm_attach(&keymem, l4re_ds_size(mem), L4RE_RM_SEARCH_ADDR, mem, 0,
251.171 + L4_PAGESHIFT))
251.172 + return 1;
251.173 +
251.174 + /* Show the keypad state. */
251.175 +
251.176 + keypad = (uint32_t *) keymem;
251.177 +
251.178 + while (1) show_keypad();
251.179 +
251.180 + return 0;
251.181 +}
252.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
252.2 +++ b/pkg/landfall-examples/letux400_backlight/Makefile Sun May 13 01:34:16 2018 +0200
252.3 @@ -0,0 +1,8 @@
252.4 +PKGDIR ?= ../..
252.5 +L4DIR ?= $(PKGDIR)/../..
252.6 +
252.7 +TARGET = ex_letux400_backlight
252.8 +SRC_CC = letux400_backlight.cc
252.9 +REQUIRES_LIBS = libio l4re_c-util libdevice-backlight-client libdevice-input-keypad libdrivers-keypad-letux400
252.10 +
252.11 +include $(L4DIR)/mk/prog.mk
253.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
253.2 +++ b/pkg/landfall-examples/letux400_backlight/letux400_backlight.cc Sun May 13 01:34:16 2018 +0200
253.3 @@ -0,0 +1,109 @@
253.4 +/*
253.5 + * Access the keypad to modify the backlight on the Letux 400.
253.6 + *
253.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
253.8 + *
253.9 + * This program is free software; you can redistribute it and/or
253.10 + * modify it under the terms of the GNU General Public License as
253.11 + * published by the Free Software Foundation; either version 2 of
253.12 + * the License, or (at your option) any later version.
253.13 + *
253.14 + * This program is distributed in the hope that it will be useful,
253.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
253.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
253.17 + * GNU General Public License for more details.
253.18 + *
253.19 + * You should have received a copy of the GNU General Public License
253.20 + * along with this program; if not, write to the Free Software
253.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
253.22 + * Boston, MA 02110-1301, USA
253.23 + */
253.24 +
253.25 +#include <l4/devices/backlight-client.h>
253.26 +#include <l4/devices/input-keypad-client.h>
253.27 +
253.28 +#include <l4/re/env>
253.29 +#include <l4/sys/capability>
253.30 +
253.31 +#include <l4/re/event_enums.h>
253.32 +#include <l4/util/util.h>
253.33 +
253.34 +/* Backlight level. */
253.35 +
253.36 +enum Letux400_backlight_levels
253.37 +{
253.38 + Letux400_backlight_min_level = 0,
253.39 + Letux400_backlight_max_level = 300,
253.40 + Letux400_backlight_step = 25,
253.41 +};
253.42 +
253.43 +static int backlight_level = 250;
253.44 +
253.45 +/* Key state. */
253.46 +
253.47 +static int modifier_set = 0;
253.48 +
253.49 +/* Backlight device abstractions. */
253.50 +
253.51 +static L4::Cap<Backlight_device_interface> backlight_device;
253.52 +
253.53 +
253.54 +
253.55 +/* Input event handler. */
253.56 +
253.57 +static void handler(Input_event event, void *priv)
253.58 +{
253.59 + (void) priv;
253.60 +
253.61 + /* Track the state of the modifier key. */
253.62 +
253.63 + if (event.code == L4RE_KEY_SLEEP)
253.64 + modifier_set = event.value;
253.65 +
253.66 + if (!event.value || !modifier_set)
253.67 + return;
253.68 +
253.69 + /* Upon keypress events, test controls and update the backlight. */
253.70 +
253.71 + switch (event.code)
253.72 + {
253.73 + case L4RE_KEY_DOWN:
253.74 + if (backlight_level < Letux400_backlight_min_level + Letux400_backlight_step)
253.75 + backlight_level = Letux400_backlight_min_level;
253.76 + else
253.77 + backlight_level -= Letux400_backlight_step;
253.78 + break;
253.79 +
253.80 + case L4RE_KEY_UP:
253.81 + if (backlight_level > Letux400_backlight_max_level - Letux400_backlight_step)
253.82 + backlight_level = Letux400_backlight_max_level;
253.83 + else
253.84 + backlight_level += Letux400_backlight_step;
253.85 + break;
253.86 +
253.87 + default: return;
253.88 + }
253.89 +
253.90 + /* Use the backlight device to update the backlight level. */
253.91 +
253.92 + backlight_device->set_brightness(backlight_level);
253.93 +}
253.94 +
253.95 +
253.96 +
253.97 +int main(void)
253.98 +{
253.99 + Keypad *keypad = Keypad::get_keypad();
253.100 + Input_keypad_client client(keypad);
253.101 +
253.102 + /* Obtain a reference to the PWM device. */
253.103 +
253.104 + backlight_device = L4Re::Env::env()->get_cap<Backlight_device_interface>("backlight");
253.105 + if (!backlight_device.is_valid()) return 1;
253.106 +
253.107 + client.attach(handler, 0);
253.108 +
253.109 + l4_sleep_forever();
253.110 +
253.111 + return 0;
253.112 +}
254.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
254.2 +++ b/pkg/landfall-examples/letux400_keypad/Makefile Sun May 13 01:34:16 2018 +0200
254.3 @@ -0,0 +1,8 @@
254.4 +PKGDIR ?= ../..
254.5 +L4DIR ?= $(PKGDIR)/../..
254.6 +
254.7 +TARGET = ex_letux400_keypad
254.8 +SRC_C = letux400_keypad.c memory.c
254.9 +REQUIRES_LIBS = libio l4re_c-util libdrivers-gpio
254.10 +
254.11 +include $(L4DIR)/mk/prog.mk
255.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
255.2 +++ b/pkg/landfall-examples/letux400_keypad/letux400_keypad.c Sun May 13 01:34:16 2018 +0200
255.3 @@ -0,0 +1,205 @@
255.4 +/*
255.5 + * Access the keypad GPIOs on the Letux 400 notebook computer.
255.6 + *
255.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
255.8 + *
255.9 + * This program is free software; you can redistribute it and/or
255.10 + * modify it under the terms of the GNU General Public License as
255.11 + * published by the Free Software Foundation; either version 2 of
255.12 + * the License, or (at your option) any later version.
255.13 + *
255.14 + * This program is distributed in the hope that it will be useful,
255.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
255.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
255.17 + * GNU General Public License for more details.
255.18 + *
255.19 + * You should have received a copy of the GNU General Public License
255.20 + * along with this program; if not, write to the Free Software
255.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
255.22 + * Boston, MA 02110-1301, USA
255.23 + */
255.24 +
255.25 +#include <l4/devices/gpio-jz4730.h>
255.26 +#include <l4/re/c/util/video/goos_fb.h>
255.27 +#include <l4/re/c/video/view.h>
255.28 +#include <l4/sys/cache.h>
255.29 +#include <l4/util/util.h>
255.30 +
255.31 +#include <stdio.h>
255.32 +#include <stdint.h>
255.33 +#include <unistd.h>
255.34 +
255.35 +#include "memory.h"
255.36 +
255.37 +enum Jz4730_keypad_gpio
255.38 +{
255.39 + Jz4730_keypad_gpio_inputs_count = 8,
255.40 + Jz4730_keypad_gpio_outputs_count = 17,
255.41 +};
255.42 +
255.43 +/* Port A input pins. */
255.44 +
255.45 +const uint8_t Jz4730_keypad_inputs[Jz4730_keypad_gpio_inputs_count] = {
255.46 + 0, 1, 2, 3, 4, 5, 6, 7
255.47 +};
255.48 +
255.49 +const Pin_slice Jz4730_keypad_inputs_mask = {.mask=0x000000ff, .offset=0};
255.50 +
255.51 +/* Port D output pins. */
255.52 +
255.53 +const uint8_t Jz4730_keypad_outputs[Jz4730_keypad_gpio_outputs_count] = {
255.54 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29
255.55 +};
255.56 +
255.57 +const Pin_slice Jz4730_keypad_outputs_mask = {.mask=0x2000ffff, .offset=0};
255.58 +
255.59 +/* Video abstractions. */
255.60 +
255.61 +static l4re_util_video_goos_fb_t gfb;
255.62 +static l4re_video_view_info_t fbi;
255.63 +static void *fb;
255.64 +
255.65 +/* Peripheral memory regions. */
255.66 +
255.67 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
255.68 +
255.69 +/* GPIO abstractions. */
255.70 +
255.71 +static void *gpio_port_a, *gpio_port_d;
255.72 +
255.73 +/* Keypad status. */
255.74 +
255.75 +uint32_t keypad[Jz4730_keypad_gpio_outputs_count];
255.76 +
255.77 +
255.78 +
255.79 +/* Initialise the pins for scanning the keypad. */
255.80 +
255.81 +static void init_keyscan(void)
255.82 +{
255.83 + jz4730_gpio_multi_setup(gpio_port_a, &Jz4730_keypad_inputs_mask, Fix_input, 0);
255.84 + jz4730_gpio_multi_config_pull(gpio_port_a, &Jz4730_keypad_inputs_mask, Pull_up);
255.85 + jz4730_gpio_multi_setup(gpio_port_d, &Jz4730_keypad_outputs_mask, Fix_input, 0);
255.86 +}
255.87 +
255.88 +/*
255.89 +Scan the keypad by enabling each output column and inspecting each input row.
255.90 +Store each column bitmap in the keypad array.
255.91 +*/
255.92 +
255.93 +static void scan_keypad(void)
255.94 +{
255.95 + uint8_t column, row;
255.96 + uint32_t value;
255.97 +
255.98 + for (column = 0; column < Jz4730_keypad_gpio_outputs_count; column++)
255.99 + {
255.100 + jz4730_gpio_setup(gpio_port_d, Jz4730_keypad_outputs[column], Fix_output, 0);
255.101 + l4_sleep(1);
255.102 +
255.103 + value = 0;
255.104 +
255.105 + for (row = 0; row < Jz4730_keypad_gpio_inputs_count; row++)
255.106 + value = (value << 1) | (jz4730_gpio_get(gpio_port_a, Jz4730_keypad_inputs[row]) ? 0 : 1);
255.107 +
255.108 + keypad[column] = value;
255.109 +
255.110 + jz4730_gpio_setup(gpio_port_d, Jz4730_keypad_outputs[column], Fix_input, 0);
255.111 + }
255.112 +}
255.113 +
255.114 +static uint32_t bitmask(uint32_t size)
255.115 +{
255.116 + return (1 << size) - 1;
255.117 +}
255.118 +
255.119 +static uint32_t truncate_channel(uint32_t value, uint32_t size)
255.120 +{
255.121 + return (value >> (8 - size)) & bitmask(size);
255.122 +}
255.123 +
255.124 +static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value)
255.125 +{
255.126 + if (bpp <= 8) *(uint8_t *) pos = value;
255.127 + else if (bpp <= 16) *(uint16_t *) pos = value;
255.128 + else *(uint32_t *) pos = value;
255.129 +}
255.130 +
255.131 +/* Show the state of a key on the display. */
255.132 +
255.133 +static void show_keystate(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb)
255.134 +{
255.135 + uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
255.136 + uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel;
255.137 + uint32_t bytes_per_line = fbi.bytes_per_line;
255.138 + uint32_t pos;
255.139 + uint32_t col, row;
255.140 +
255.141 + rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) |
255.142 + (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) |
255.143 + (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift);
255.144 +
255.145 + for (row = 0; row < h; row++)
255.146 + {
255.147 + pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel;
255.148 +
255.149 + for (col = 0; col < w; col++)
255.150 + {
255.151 + set_pixel(pos, bpp, rgb);
255.152 + pos += bytes_per_pixel;
255.153 + }
255.154 + }
255.155 +}
255.156 +
255.157 +/* Show the keypad status on the display. */
255.158 +
255.159 +static void show_keypad(void)
255.160 +{
255.161 + uint32_t colsize = fbi.width / Jz4730_keypad_gpio_outputs_count,
255.162 + rowsize = fbi.height / Jz4730_keypad_gpio_inputs_count;
255.163 + uint8_t column, row;
255.164 + uint32_t mask;
255.165 +
255.166 + for (column = 0; column < Jz4730_keypad_gpio_outputs_count; column++)
255.167 +
255.168 + for (row = 0, mask = 1 << (Jz4730_keypad_gpio_inputs_count - 1);
255.169 + row < Jz4730_keypad_gpio_inputs_count;
255.170 + row++, mask >>= 1)
255.171 +
255.172 + show_keystate(column * colsize, row * rowsize, colsize, rowsize,
255.173 + keypad[column] & mask ? 0xffffff : 0);
255.174 +
255.175 + /* Refresh the display. */
255.176 +
255.177 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height);
255.178 +}
255.179 +
255.180 +int main(void)
255.181 +{
255.182 + int result;
255.183 +
255.184 + if ((result = get_memory("jz4730-gpio", &gpio_virt_base, &gpio_virt_base_end)) < 0)
255.185 + return 1;
255.186 +
255.187 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
255.188 + return 1;
255.189 +
255.190 + if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
255.191 + return 1;
255.192 +
255.193 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
255.194 + return 1;
255.195 +
255.196 + gpio_port_a = jz4730_gpio_init(gpio_virt_base, gpio_virt_base + 0x30, 32);
255.197 + gpio_port_d = jz4730_gpio_init(gpio_virt_base + 0x90, gpio_virt_base + 0xc0, 32);
255.198 +
255.199 + init_keyscan();
255.200 +
255.201 + while (1)
255.202 + {
255.203 + scan_keypad();
255.204 + show_keypad();
255.205 + }
255.206 +
255.207 + return 0;
255.208 +}
256.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
256.2 +++ b/pkg/landfall-examples/letux400_keypad/memory.c Sun May 13 01:34:16 2018 +0200
256.3 @@ -0,0 +1,105 @@
256.4 +/*
256.5 + * Memory allocation utility functions.
256.6 + *
256.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
256.8 + * Subject to other copyrights, being derived from the existing L4Re
256.9 + * LCD driver implementations.
256.10 + *
256.11 + * This file is part of TUD:OS and distributed under the terms of the
256.12 + * GNU General Public License 2.
256.13 + * Please see the COPYING-GPL-2 file for details.
256.14 + */
256.15 +
256.16 +#include <stdio.h>
256.17 +
256.18 +#include "memory.h"
256.19 +#include <l4/io/io.h>
256.20 +#include <l4/re/env.h>
256.21 +#include <l4/re/c/mem_alloc.h>
256.22 +#include <l4/re/c/util/cap_alloc.h>
256.23 +#include <l4/util/util.h>
256.24 +#include <l4/vbus/vbus.h>
256.25 +
256.26 +/* Internal memory allocation/mapping functions. */
256.27 +
256.28 +static char const *resource_type(enum l4io_resource_types_t type)
256.29 +{
256.30 + switch (type)
256.31 + {
256.32 + case L4VBUS_RESOURCE_INVALID:
256.33 + return "INVALID";
256.34 +
256.35 + case L4VBUS_RESOURCE_IRQ:
256.36 + return "IRQ";
256.37 +
256.38 + case L4VBUS_RESOURCE_MEM:
256.39 + return "MEMORY";
256.40 +
256.41 + default:
256.42 + return "OTHER";
256.43 + }
256.44 +}
256.45 +
256.46 +int get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
256.47 +{
256.48 + int result = l4io_lookup_device(hid, dh, 0, rh);
256.49 +
256.50 + if (result < 0)
256.51 + printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");
256.52 +
256.53 + return result;
256.54 +}
256.55 +
256.56 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
256.57 + enum l4io_resource_types_t type)
256.58 +{
256.59 + int current = 0, result = 0;
256.60 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
256.61 +
256.62 + do
256.63 + {
256.64 + result = l4vbus_get_resource(vbus, dh, current, res);
256.65 +
256.66 + if (result)
256.67 + printf("Could not access resource of type %s.\n", resource_type(type));
256.68 + else
256.69 + printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,
256.70 + resource_type(res->type), res->start, res->end);
256.71 +
256.72 + current++;
256.73 + }
256.74 + while ((!result) && (res->type != type));
256.75 +
256.76 + return result;
256.77 +}
256.78 +
256.79 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
256.80 +{
256.81 + l4io_device_handle_t dh;
256.82 + l4io_resource_handle_t rh;
256.83 + l4io_resource_t res;
256.84 + int result;
256.85 +
256.86 + result = get_device(hid, &dh, &rh);
256.87 +
256.88 + if (result < 0)
256.89 + return result;
256.90 +
256.91 + result = get_resource(dh, &res, L4IO_RESOURCE_MEM);
256.92 +
256.93 + if (result)
256.94 + return result;
256.95 +
256.96 + if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,
256.97 + L4IO_MEM_NONCACHED, start)))
256.98 + {
256.99 + printf("Could not get address for '%s'.\n", hid);
256.100 + return result;
256.101 + }
256.102 +
256.103 + printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);
256.104 +
256.105 + *end = *start + (res.end - res.start + 1);
256.106 +
256.107 + return 0;
256.108 +}
257.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
257.2 +++ b/pkg/landfall-examples/letux400_keypad/memory.h Sun May 13 01:34:16 2018 +0200
257.3 @@ -0,0 +1,28 @@
257.4 +/*
257.5 + * Memory allocation utility functions.
257.6 + *
257.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
257.8 + * Subject to other copyrights, being derived from the existing L4Re
257.9 + * LCD driver implementations.
257.10 + *
257.11 + * This file is part of TUD:OS and distributed under the terms of the
257.12 + * GNU General Public License 2.
257.13 + * Please see the COPYING-GPL-2 file for details.
257.14 + */
257.15 +
257.16 +#ifndef __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__
257.17 +#define __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__
257.18 +
257.19 +#include <l4/io/io.h>
257.20 +#include <l4/re/env.h>
257.21 +#include <l4/util/util.h>
257.22 +
257.23 +int get_device(char const *hid, l4io_device_handle_t *dh,
257.24 + l4io_resource_handle_t *rh);
257.25 +
257.26 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
257.27 + enum l4io_resource_types_t type);
257.28 +
257.29 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end);
257.30 +
257.31 +#endif /* __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__ */
258.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
258.2 +++ b/pkg/landfall-examples/letux400_keypad_driver/Makefile Sun May 13 01:34:16 2018 +0200
258.3 @@ -0,0 +1,9 @@
258.4 +PKGDIR ?= ../..
258.5 +L4DIR ?= $(PKGDIR)/../..
258.6 +
258.7 +TARGET = ex_letux400_keypad_driver
258.8 +SRC_CC = letux400_keypad_driver.cc
258.9 +SRC_DATA = unifont.tff
258.10 +REQUIRES_LIBS = libio l4re_c-util libdevice-input-keypad libdrivers-keypad-letux400 mag-gfx
258.11 +
258.12 +include $(L4DIR)/mk/prog.mk
259.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
259.2 +++ b/pkg/landfall-examples/letux400_keypad_driver/letux400_keypad_driver.cc Sun May 13 01:34:16 2018 +0200
259.3 @@ -0,0 +1,251 @@
259.4 +/*
259.5 + * Access the keypad on the configured device using an input driver.
259.6 + *
259.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
259.8 + *
259.9 + * This program is free software; you can redistribute it and/or
259.10 + * modify it under the terms of the GNU General Public License as
259.11 + * published by the Free Software Foundation; either version 2 of
259.12 + * the License, or (at your option) any later version.
259.13 + *
259.14 + * This program is distributed in the hope that it will be useful,
259.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
259.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
259.17 + * GNU General Public License for more details.
259.18 + *
259.19 + * You should have received a copy of the GNU General Public License
259.20 + * along with this program; if not, write to the Free Software
259.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
259.22 + * Boston, MA 02110-1301, USA
259.23 + *
259.24 + *
259.25 + * Font definitions and licence (see unifont.tff for bitmap data derived from
259.26 + * GNU Unifont's unifont.hex file):
259.27 + *
259.28 + * Copyright (C) 1998-2003 Roman Czyborra (http://czyborra.com/)
259.29 + *
259.30 + * All glyphs are released under the GNU General Public License
259.31 + * (GPL) version 2 or (at your option) a later version, with the
259.32 + * GNU font embedding exception:
259.33 + *
259.34 + * ** GPL v2.0 license with font embedding exception:
259.35 + *
259.36 + * As a special exception, if you create a document which
259.37 + * uses this font, and embed this font or unaltered portions
259.38 + * of this font into the document, this font does not by
259.39 + * itself cause the resulting document to be covered by
259.40 + * the GNU General Public License. This exception does not
259.41 + * however invalidate any other reasons why the document
259.42 + * might be covered by the GNU General Public License.
259.43 + * If you modify this font, you may extend this exception
259.44 + * to your version of the font, but you are not obligated
259.45 + * to do so. If you do not wish to do so, delete this
259.46 + * exception statement from your version.
259.47 + */
259.48 +
259.49 +#include <l4/devices/input-keypad-client.h>
259.50 +
259.51 +#include <l4/re/c/util/video/goos_fb.h>
259.52 +#include <l4/re/c/video/view.h>
259.53 +#include <l4/util/util.h>
259.54 +
259.55 +#include <l4/mag-gfx/canvas>
259.56 +#include <l4/mag-gfx/font>
259.57 +#include <l4/mag-gfx/geometry>
259.58 +#include <l4/mag-gfx/gfx_colors>
259.59 +#include <l4/mag-gfx/mem_factory>
259.60 +
259.61 +#include <stdint.h>
259.62 +#include <string.h>
259.63 +
259.64 +/* Video abstractions. */
259.65 +
259.66 +static l4re_util_video_goos_fb_t gfb;
259.67 +static l4re_video_view_info_t view_info;
259.68 +static void *fb = 0;
259.69 +
259.70 +/* Bundled font data. */
259.71 +
259.72 +extern char const _binary_unifont_tff_start[];
259.73 +
259.74 +/* Screen abstractions. */
259.75 +
259.76 +using namespace Mag_gfx;
259.77 +
259.78 +static Font *_font = 0;
259.79 +static Canvas *_screen = 0;
259.80 +
259.81 +
259.82 +
259.83 +/* Factories for certain pixel formats. */
259.84 +
259.85 +static Mem::Factory<Rgb16> _rgb16;
259.86 +static Mem::Factory<Rgb32> _rgb32;
259.87 +
259.88 +
259.89 +
259.90 +/* Key to character conversion function. */
259.91 +
259.92 +static const char *keys_to_strings[] = {
259.93 +
259.94 + 0, "Escape", "1", "2", "3", "4", "5", "6", "7", "8",
259.95 +
259.96 + "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E", "R",
259.97 +
259.98 + "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Left Ctrl",
259.99 +
259.100 + "A", "S", "D", "F", "G", "H", "J", "K", "L", ";",
259.101 +
259.102 + "'", "`", "Left Shift", "\\", "Z", "X", "C", "V", "B", "N",
259.103 +
259.104 + "M", ",", ".", "/", "Right Shift", "Keypad *", "Left Alt", "Space",
259.105 + "Caps Lock", "F1",
259.106 +
259.107 + "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "Num Lock",
259.108 +
259.109 + "Scroll Lock", "Keypad 7", "Keypad 8", "Keypad 9", "Keypad -", "Keypad 4",
259.110 + "Keypad 5", "Keypad 6", "Keypad +", "Keypad 1",
259.111 +
259.112 + "Keypad 2", "Keypad 3", "Keypad 0", "Keypad .", 0, 0, "#102", "F11", "F12", 0,
259.113 +
259.114 + 0, 0, 0, 0, 0, 0, "Keypad Enter", "Right Ctrl", "Keypad /", "SysRq",
259.115 +
259.116 + "Right Alt", "Line Feed", "Home", "Up", "Page Up", "Left", "Right", "End",
259.117 + "Down", "Page Down",
259.118 +
259.119 + "Insert", "Delete", "Macro", "Mute", "Volume Down", "Volume Up", "Power",
259.120 + "Keypad =", "Keypad +-", "Pause",
259.121 +};
259.122 +
259.123 +static const char null_string[] = "Unknown";
259.124 +
259.125 +const int keys_to_strings_length = 120;
259.126 +
259.127 +static const char *key_to_string(int key)
259.128 +{
259.129 + return key < keys_to_strings_length ? keys_to_strings[key] : 0;
259.130 +}
259.131 +
259.132 +/* Show the keypad event status on the display. */
259.133 +
259.134 +static uint8_t row = 0;
259.135 +static uint32_t text_x = 0, text_y = 0, next_y = 0;
259.136 +
259.137 +static void handler(Input_event event, void *priv)
259.138 +{
259.139 + uint32_t colsize = view_info.width / 10,
259.140 + rowsize = view_info.height / 20;
259.141 + uint8_t column;
259.142 + uint16_t mask;
259.143 +
259.144 + /* Convert the key code into a bit pattern. */
259.145 +
259.146 + if (!priv)
259.147 + {
259.148 + for (column = 0, mask = (1 << 9); column < 10; column++, mask >>= 1)
259.149 + _screen->draw_box(Rect(Point(column * colsize, row * rowsize), Area(colsize, rowsize)),
259.150 + event.code & mask ? event.value ? Rgb32::Color(0, 255, 0) : Rgb32::Color(255, 0, 0)
259.151 + : Rgb32::Color(0, 0, 0));
259.152 +
259.153 + /* Advance to the next row, wrapping around. */
259.154 +
259.155 + row = (row + 1) % 20;
259.156 + }
259.157 +
259.158 + /* Or produce a string. */
259.159 +
259.160 + else if (event.value)
259.161 + {
259.162 + const char *s = ((const char *(*)(int)) priv)(event.code);
259.163 + Rgba32::Color col;
259.164 +
259.165 + if (!s)
259.166 + {
259.167 + s = null_string;
259.168 + col = Rgba32::Color(255, 0, 0, Rgba32::Color::Amax);
259.169 + }
259.170 + else
259.171 + col = Rgba32::Color(255, 255, 255, Rgba32::Color::Amax);
259.172 +
259.173 + Area box = _font->str_sz(s, strlen(s));
259.174 +
259.175 + /* Test for enough space horizontally. */
259.176 +
259.177 + if (text_x + box.w() > view_info.width)
259.178 + {
259.179 + text_x = 0;
259.180 + text_y = next_y;
259.181 + next_y = text_y + box.h();
259.182 + }
259.183 +
259.184 + /* Expand the line height, if appropriate. */
259.185 +
259.186 + else if (text_y + box.h() > next_y)
259.187 + next_y += box.h();
259.188 +
259.189 + /* Test for enough space vertically. */
259.190 +
259.191 + if (next_y > view_info.height)
259.192 + {
259.193 + text_x = 0;
259.194 + text_y = 0;
259.195 + next_y = box.h();
259.196 + }
259.197 +
259.198 + Point p(text_x, text_y);
259.199 +
259.200 + _screen->draw_box(Rect(p, box), Rgb32::Color(0, 0, 0));
259.201 + _screen->draw_string(p, _font, col, s, strlen(s));
259.202 +
259.203 + /* Move to the next position. */
259.204 +
259.205 + text_x += box.w();
259.206 + }
259.207 +
259.208 + /* Refresh the display. */
259.209 +
259.210 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, view_info.width, view_info.height);
259.211 +}
259.212 +
259.213 +/* Arguments: [ chars ] */
259.214 +
259.215 +int main(int argc, char *argv[])
259.216 +{
259.217 + Keypad *keypad = Keypad::get_keypad();
259.218 + Input_keypad_client client(keypad);
259.219 +
259.220 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
259.221 + return 1;
259.222 +
259.223 + if (l4re_util_video_goos_fb_view_info(&gfb, &view_info))
259.224 + return 1;
259.225 +
259.226 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
259.227 + return 1;
259.228 +
259.229 + /* Obtain a canvas for the framebuffer. */
259.230 +
259.231 + Factory *factory;
259.232 +
259.233 + if (view_info.pixel_info.bytes_per_pixel == 2)
259.234 + factory = &_rgb16;
259.235 + else
259.236 + factory = &_rgb32;
259.237 +
259.238 + Canvas *screen = factory->create_canvas((void *) ((unsigned long) fb + view_info.buffer_offset),
259.239 + Area(view_info.width, view_info.height),
259.240 + view_info.bytes_per_line);
259.241 +
259.242 + Font font(&_binary_unifont_tff_start[0]);
259.243 +
259.244 + _screen = screen;
259.245 + _font = &font;
259.246 +
259.247 + /* Attach the event handler and wait for events. */
259.248 +
259.249 + client.attach(handler, (argc > 1) && (!strcmp(argv[1], "chars")) ? (void *) key_to_string : 0);
259.250 +
259.251 + l4_sleep_forever();
259.252 +
259.253 + return 0;
259.254 +}
260.1 Binary file pkg/landfall-examples/letux400_keypad_driver/unifont.tff has changed
261.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
261.2 +++ b/pkg/landfall-examples/letux400_keypad_physical/Makefile Sun May 13 01:34:16 2018 +0200
261.3 @@ -0,0 +1,8 @@
261.4 +PKGDIR ?= ../..
261.5 +L4DIR ?= $(PKGDIR)/../..
261.6 +
261.7 +TARGET = ex_letux400_keypad_physical
261.8 +SRC_C = letux400_keypad_physical.c
261.9 +REQUIRES_LIBS = l4re_c-util
261.10 +
261.11 +include $(L4DIR)/mk/prog.mk
262.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
262.2 +++ b/pkg/landfall-examples/letux400_keypad_physical/letux400_keypad_physical.c Sun May 13 01:34:16 2018 +0200
262.3 @@ -0,0 +1,314 @@
262.4 +/*
262.5 + * Display the physical keypad matrix layout for the Letux 400 notebook
262.6 + * computer.
262.7 + *
262.8 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
262.9 + *
262.10 + * This program is free software; you can redistribute it and/or
262.11 + * modify it under the terms of the GNU General Public License as
262.12 + * published by the Free Software Foundation; either version 2 of
262.13 + * the License, or (at your option) any later version.
262.14 + *
262.15 + * This program is distributed in the hope that it will be useful,
262.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
262.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
262.18 + * GNU General Public License for more details.
262.19 + *
262.20 + * You should have received a copy of the GNU General Public License
262.21 + * along with this program; if not, write to the Free Software
262.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
262.23 + * Boston, MA 02110-1301, USA
262.24 + */
262.25 +
262.26 +#include <l4/re/c/rm.h>
262.27 +#include <l4/re/c/util/cap_alloc.h>
262.28 +#include <l4/re/env.h>
262.29 +#include <l4/util/util.h>
262.30 +#include <l4/sys/ipc.h>
262.31 +
262.32 +#include <l4/re/c/util/video/goos_fb.h>
262.33 +#include <l4/re/c/video/view.h>
262.34 +
262.35 +#include <stdio.h>
262.36 +#include <stdint.h>
262.37 +#include <stdlib.h>
262.38 +#include <unistd.h>
262.39 +
262.40 +enum Jz4730_keypad_gpio
262.41 +{
262.42 + Jz4730_keypad_gpio_inputs_count = 8,
262.43 + Jz4730_keypad_gpio_outputs_count = 17,
262.44 +};
262.45 +
262.46 +/* Video abstractions. */
262.47 +
262.48 +static l4re_util_video_goos_fb_t gfb;
262.49 +static l4re_video_view_info_t fbi;
262.50 +static void *fb;
262.51 +
262.52 +/* Keypad status and dimensions. */
262.53 +
262.54 +uint32_t *keypad = 0;
262.55 +void *keymem = 0;
262.56 +int columns = Jz4730_keypad_gpio_outputs_count, rows = Jz4730_keypad_gpio_inputs_count;
262.57 +
262.58 +/* Position units: 0.1mm */
262.59 +
262.60 +enum {
262.61 + SPC = 600, CAPS = 240, TAB = 200, LSH = 184, M = 160, S = 136, XS = 120,
262.62 + WIDTH = 2040, HEIGHT = 800, ROWS = 6,
262.63 +};
262.64 +
262.65 +/*
262.66 +S(15) Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 Num Sys Ins Del
262.67 +XS(1)/M(12) ` 1 2 3 4 5 6 7 8 9 0 - Bsp
262.68 +TAB(1)/M(10)/XS(2) Tab Q W E R T Y U I O P = \
262.69 +CAPS(1)/M(9)/XS(1)/CAPS(1) Caps A S D F G H J K L ; Enter
262.70 +LSH(1)/XS(1)/M(7)/XS(4)/S(1) Sh \ Z X C V B N M , . / Up Sh
262.71 +XS(5)/SPC(1)/XS(7) Fn Ctr Zzz Alt Pau Space Mnu [ ] ' Lt Dn Rt
262.72 +*/
262.73 +
262.74 +enum {
262.75 + SIZE_KEY_ESC = S, SIZE_KEY_F1 = S, SIZE_KEY_F2 = S, SIZE_KEY_F3 = S, SIZE_KEY_F4 = S,
262.76 + SIZE_KEY_F5 = S, SIZE_KEY_F6 = S, SIZE_KEY_F7 = S, SIZE_KEY_F8 = S, SIZE_KEY_F9 = S,
262.77 + SIZE_KEY_F10 = S, SIZE_KEY_NUMLOCK = S, SIZE_KEY_SYSRQ = S, SIZE_KEY_INSERT = S,
262.78 + SIZE_KEY_DELETE = S,
262.79 +
262.80 + SIZE_KEY_GRAVE = XS, SIZE_KEY_1 = M, SIZE_KEY_2 = M, SIZE_KEY_3 = M, SIZE_KEY_4 = M,
262.81 + SIZE_KEY_5 = M, SIZE_KEY_6 = M, SIZE_KEY_7 = M, SIZE_KEY_8 = M, SIZE_KEY_9 = M,
262.82 + SIZE_KEY_0 = M, SIZE_KEY_MINUS = M, SIZE_KEY_BACKSPACE = M,
262.83 +
262.84 + SIZE_KEY_TAB = TAB, SIZE_KEY_Q = M, SIZE_KEY_W = M, SIZE_KEY_E = M, SIZE_KEY_R = M,
262.85 + SIZE_KEY_T = M, SIZE_KEY_Y = M, SIZE_KEY_U = M, SIZE_KEY_I = M, SIZE_KEY_O = M,
262.86 + SIZE_KEY_P = M, SIZE_KEY_EQUAL = XS, SIZE_KEY_RIGHTBACKSLASH = XS,
262.87 +
262.88 + SIZE_KEY_CAPSLOCK = CAPS, SIZE_KEY_A = M, SIZE_KEY_S = M, SIZE_KEY_D = M, SIZE_KEY_F = M,
262.89 + SIZE_KEY_G = M, SIZE_KEY_H = M, SIZE_KEY_J = M, SIZE_KEY_K = M, SIZE_KEY_L = M,
262.90 + SIZE_KEY_SEMICOLON = XS, SIZE_KEY_ENTER = CAPS,
262.91 +
262.92 + SIZE_KEY_LEFTSHIFT = LSH, SIZE_KEY_LEFTBACKSLASH = XS, SIZE_KEY_Z = M, SIZE_KEY_X = M, SIZE_KEY_C = M,
262.93 + SIZE_KEY_V = M, SIZE_KEY_B = M, SIZE_KEY_N = M, SIZE_KEY_M = M, SIZE_KEY_COMMA = XS,
262.94 + SIZE_KEY_DOT = XS, SIZE_KEY_SLASH = XS, SIZE_KEY_UP = XS, SIZE_KEY_RIGHTSHIFT = S,
262.95 +
262.96 + SIZE_KEY_FN = XS, SIZE_KEY_LEFTCTRL = XS, SIZE_KEY_SLEEP = XS, SIZE_KEY_LEFTALT = XS, SIZE_KEY_PAUSE = XS,
262.97 + SIZE_KEY_SPACE = SPC, SIZE_KEY_MENU = XS, SIZE_KEY_LEFTBRACE = XS, SIZE_KEY_RIGHTBRACE = XS,
262.98 + SIZE_KEY_APOSTROPHE = XS, SIZE_KEY_LEFT = XS, SIZE_KEY_DOWN = XS, SIZE_KEY_RIGHT = XS,
262.99 +};
262.100 +
262.101 +enum {
262.102 + XPOS_KEY_ESC = 0, XPOS_KEY_F1 = S, XPOS_KEY_F2 = 2*S, XPOS_KEY_F3 = 3*S, XPOS_KEY_F4 = 4*S,
262.103 + XPOS_KEY_F5 = 5*S, XPOS_KEY_F6 = 6*S, XPOS_KEY_F7 = 7*S, XPOS_KEY_F8 = 8*S, XPOS_KEY_F9 = 9*S,
262.104 + XPOS_KEY_F10 = 10*S, XPOS_KEY_NUMLOCK = 11*S, XPOS_KEY_SYSRQ = 12*S, XPOS_KEY_INSERT = 13*S,
262.105 + XPOS_KEY_DELETE = 14*S,
262.106 +
262.107 + XPOS_KEY_GRAVE = 0, XPOS_KEY_1 = XS, XPOS_KEY_2 = XS+M, XPOS_KEY_3 = XS+2*M, XPOS_KEY_4 = XS+3*M,
262.108 + XPOS_KEY_5 = XS+4*M, XPOS_KEY_6 = XS+5*M, XPOS_KEY_7 = XS+6*M, XPOS_KEY_8 = XS+7*M, XPOS_KEY_9 = XS+8*M,
262.109 + XPOS_KEY_0 = XS+9*M, XPOS_KEY_MINUS = XS+10*M, XPOS_KEY_BACKSPACE = XS+11*M,
262.110 +
262.111 + XPOS_KEY_TAB = 0, XPOS_KEY_Q = TAB, XPOS_KEY_W = TAB+M, XPOS_KEY_E = TAB+2*M, XPOS_KEY_R = TAB+3*M,
262.112 + XPOS_KEY_T = TAB+4*M, XPOS_KEY_Y = TAB+5*M, XPOS_KEY_U = TAB+6*M, XPOS_KEY_I = TAB+7*M, XPOS_KEY_O = TAB+8*M,
262.113 + XPOS_KEY_P = TAB+9*M, XPOS_KEY_EQUAL = TAB+10*M, XPOS_KEY_RIGHTBACKSLASH = TAB+10*M+XS,
262.114 +
262.115 + XPOS_KEY_CAPSLOCK = 0, XPOS_KEY_A = CAPS, XPOS_KEY_S = CAPS+M, XPOS_KEY_D = CAPS+2*M, XPOS_KEY_F = CAPS+3*M,
262.116 + XPOS_KEY_G = CAPS+4*M, XPOS_KEY_H = CAPS+5*M, XPOS_KEY_J = CAPS+6*M, XPOS_KEY_K = CAPS+7*M, XPOS_KEY_L = CAPS+8*M,
262.117 + XPOS_KEY_SEMICOLON = CAPS+9*M, XPOS_KEY_ENTER = CAPS+9*M+XS,
262.118 +
262.119 + XPOS_KEY_LEFTSHIFT = 0, XPOS_KEY_LEFTBACKSLASH = LSH, XPOS_KEY_Z = LSH+XS, XPOS_KEY_X = LSH+XS+M, XPOS_KEY_C = LSH+XS+2*M,
262.120 + XPOS_KEY_V = LSH+XS+3*M, XPOS_KEY_B = LSH+XS+4*M, XPOS_KEY_N = LSH+XS+5*M, XPOS_KEY_M = LSH+XS+6*M, XPOS_KEY_COMMA = LSH+XS+7*M,
262.121 + XPOS_KEY_DOT = LSH+XS+7*M+XS, XPOS_KEY_SLASH = LSH+XS+7*M+2*XS, XPOS_KEY_UP = LSH+XS+7*M+3*XS, XPOS_KEY_RIGHTSHIFT = LSH+XS+7*M+4*XS,
262.122 +
262.123 + XPOS_KEY_FN = 0, XPOS_KEY_LEFTCTRL = XS, XPOS_KEY_SLEEP = 2*XS, XPOS_KEY_LEFTALT = 3*XS, XPOS_KEY_PAUSE = 4*XS,
262.124 + XPOS_KEY_SPACE = 5*XS, XPOS_KEY_MENU = 5*XS+SPC, XPOS_KEY_LEFTBRACE = 5*XS+SPC+XS, XPOS_KEY_RIGHTBRACE = 5*XS+SPC+2*XS,
262.125 + XPOS_KEY_APOSTROPHE = 5*XS+SPC+3*XS, XPOS_KEY_LEFT = 5*XS+SPC+4*XS, XPOS_KEY_DOWN = 5*XS+SPC+5*XS, XPOS_KEY_RIGHT = 5*XS+SPC+6*XS,
262.126 +};
262.127 +
262.128 +enum {
262.129 + YPOS_KEY_ESC = 0, YPOS_KEY_F1 = 0, YPOS_KEY_F2 = 0, YPOS_KEY_F3 = 0, YPOS_KEY_F4 = 0,
262.130 + YPOS_KEY_F5 = 0, YPOS_KEY_F6 = 0, YPOS_KEY_F7 = 0, YPOS_KEY_F8 = 0, YPOS_KEY_F9 = 0,
262.131 + YPOS_KEY_F10 = 0, YPOS_KEY_NUMLOCK = 0, YPOS_KEY_SYSRQ = 0, YPOS_KEY_INSERT = 0,
262.132 + YPOS_KEY_DELETE = 0,
262.133 +
262.134 + YPOS_KEY_GRAVE = 1, YPOS_KEY_1 = 1, YPOS_KEY_2 = 1, YPOS_KEY_3 = 1, YPOS_KEY_4 = 1,
262.135 + YPOS_KEY_5 = 1, YPOS_KEY_6 = 1, YPOS_KEY_7 = 1, YPOS_KEY_8 = 1, YPOS_KEY_9 = 1,
262.136 + YPOS_KEY_0 = 1, YPOS_KEY_MINUS = 1, YPOS_KEY_BACKSPACE = 1,
262.137 +
262.138 + YPOS_KEY_TAB = 2, YPOS_KEY_Q = 2, YPOS_KEY_W = 2, YPOS_KEY_E = 2, YPOS_KEY_R = 2,
262.139 + YPOS_KEY_T = 2, YPOS_KEY_Y = 2, YPOS_KEY_U = 2, YPOS_KEY_I = 2, YPOS_KEY_O = 2,
262.140 + YPOS_KEY_P = 2, YPOS_KEY_EQUAL = 2, YPOS_KEY_RIGHTBACKSLASH = 2,
262.141 +
262.142 + YPOS_KEY_CAPSLOCK = 3, YPOS_KEY_A = 3, YPOS_KEY_S = 3, YPOS_KEY_D = 3, YPOS_KEY_F = 3,
262.143 + YPOS_KEY_G = 3, YPOS_KEY_H = 3, YPOS_KEY_J = 3, YPOS_KEY_K = 3, YPOS_KEY_L = 3,
262.144 + YPOS_KEY_SEMICOLON = 3, YPOS_KEY_ENTER = 3,
262.145 +
262.146 + YPOS_KEY_LEFTSHIFT = 4, YPOS_KEY_LEFTBACKSLASH = 4, YPOS_KEY_Z = 4, YPOS_KEY_X = 4, YPOS_KEY_C = 4,
262.147 + YPOS_KEY_V = 4, YPOS_KEY_B = 4, YPOS_KEY_N = 4, YPOS_KEY_M = 4, YPOS_KEY_COMMA = 4,
262.148 + YPOS_KEY_DOT = 4, YPOS_KEY_SLASH = 4, YPOS_KEY_UP = 4, YPOS_KEY_RIGHTSHIFT = 4,
262.149 +
262.150 + YPOS_KEY_FN = 5, YPOS_KEY_LEFTCTRL = 5, YPOS_KEY_SLEEP = 5, YPOS_KEY_LEFTALT = 5, YPOS_KEY_PAUSE = 5,
262.151 + YPOS_KEY_SPACE = 5, YPOS_KEY_MENU = 5, YPOS_KEY_LEFTBRACE = 5, YPOS_KEY_RIGHTBRACE = 5,
262.152 + YPOS_KEY_APOSTROPHE = 5, YPOS_KEY_LEFT = 5, YPOS_KEY_DOWN = 5, YPOS_KEY_RIGHT = 5,
262.153 +};
262.154 +
262.155 +/* Keypad matrix mapping. */
262.156 +
262.157 +#define PHYS_KEY(X) {XPOS_KEY_##X, YPOS_KEY_##X, SIZE_KEY_##X}
262.158 +#define PHYS_NULL {0, 0, 0}
262.159 +
262.160 +static const uint32_t keypos[Jz4730_keypad_gpio_inputs_count][Jz4730_keypad_gpio_outputs_count][3] = {
262.161 +
262.162 +{PHYS_KEY(PAUSE), PHYS_KEY(Q), PHYS_KEY(W), PHYS_KEY(E), PHYS_KEY(R), PHYS_KEY(U), PHYS_KEY(I), PHYS_KEY(O),
262.163 + PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(P), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_NULL},
262.164 +
262.165 +{PHYS_NULL, PHYS_KEY(TAB), PHYS_KEY(CAPSLOCK), PHYS_KEY(F3), PHYS_KEY(T), PHYS_KEY(Y), PHYS_KEY(RIGHTBRACE), PHYS_KEY(F7),
262.166 + PHYS_NULL, PHYS_KEY(BACKSPACE), PHYS_NULL, PHYS_KEY(LEFTBRACE), PHYS_KEY(SLEEP), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(LEFTSHIFT)},
262.167 +
262.168 +{PHYS_NULL, PHYS_KEY(A), PHYS_KEY(S), PHYS_KEY(D), PHYS_KEY(F), PHYS_KEY(J), PHYS_KEY(K), PHYS_KEY(L),
262.169 + PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(SEMICOLON), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(UP), PHYS_KEY(RIGHTSHIFT)},
262.170 +
262.171 +{PHYS_NULL, PHYS_KEY(ESC), PHYS_KEY(LEFTBACKSLASH), PHYS_KEY(F4), PHYS_KEY(G), PHYS_KEY(H), PHYS_KEY(F6), PHYS_NULL,
262.172 + PHYS_KEY(SPACE), PHYS_NULL, PHYS_KEY(LEFTALT), PHYS_KEY(APOSTROPHE), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(DOWN), PHYS_NULL},
262.173 +
262.174 +{PHYS_NULL, PHYS_KEY(Z), PHYS_KEY(X), PHYS_KEY(C), PHYS_KEY(V), PHYS_KEY(M), PHYS_KEY(COMMA), PHYS_KEY(DOT),
262.175 + PHYS_KEY(NUMLOCK), PHYS_KEY(ENTER), PHYS_NULL, PHYS_KEY(RIGHTBACKSLASH), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(LEFT), PHYS_NULL},
262.176 +
262.177 +{PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(B), PHYS_KEY(N), PHYS_NULL, PHYS_KEY(MENU),
262.178 + PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(SLASH), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(RIGHT), PHYS_NULL},
262.179 +
262.180 +{PHYS_KEY(LEFTCTRL), PHYS_KEY(GRAVE), PHYS_NULL, PHYS_NULL, PHYS_KEY(5), PHYS_KEY(6), PHYS_KEY(EQUAL), PHYS_KEY(F8),
262.181 + PHYS_KEY(DELETE), PHYS_KEY(F9), PHYS_NULL, PHYS_KEY(MINUS), PHYS_NULL, PHYS_KEY(F2), PHYS_KEY(INSERT), PHYS_NULL, PHYS_KEY(F1)},
262.182 +
262.183 +{PHYS_KEY(F5), PHYS_KEY(1), PHYS_KEY(2), PHYS_KEY(3), PHYS_KEY(4), PHYS_KEY(7), PHYS_KEY(8), PHYS_KEY(9),
262.184 + PHYS_NULL, PHYS_NULL, PHYS_KEY(SYSRQ), PHYS_KEY(0), PHYS_KEY(F10), PHYS_NULL, PHYS_NULL, PHYS_NULL, PHYS_KEY(FN)}
262.185 +};
262.186 +
262.187 +
262.188 +
262.189 +static uint32_t bitmask(uint32_t size)
262.190 +{
262.191 + return (1 << size) - 1;
262.192 +}
262.193 +
262.194 +static uint32_t truncate_channel(uint32_t value, uint32_t size)
262.195 +{
262.196 + return (value >> (8 - size)) & bitmask(size);
262.197 +}
262.198 +
262.199 +static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value)
262.200 +{
262.201 + if (bpp <= 8) *(uint8_t *) pos = value;
262.202 + else if (bpp <= 16) *(uint16_t *) pos = value;
262.203 + else *(uint32_t *) pos = value;
262.204 +}
262.205 +
262.206 +/* Show the state of a key on the display. */
262.207 +
262.208 +static void fill_rectangle(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb)
262.209 +{
262.210 + uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
262.211 + uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel;
262.212 + uint32_t bytes_per_line = fbi.bytes_per_line;
262.213 + uint32_t pos;
262.214 + uint32_t col, row;
262.215 +
262.216 + rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) |
262.217 + (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) |
262.218 + (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift);
262.219 +
262.220 + for (row = 0; row < h; row++)
262.221 + {
262.222 + pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel;
262.223 +
262.224 + for (col = 0; col < w; col++)
262.225 + {
262.226 + set_pixel(pos, bpp, rgb);
262.227 + pos += bytes_per_pixel;
262.228 + }
262.229 + }
262.230 +}
262.231 +
262.232 +/* Show the keypad status on the display. */
262.233 +
262.234 +static void show_keypad(void)
262.235 +{
262.236 + uint32_t rowsize = fbi.height / ROWS, colsize;
262.237 + uint8_t column, row;
262.238 + uint32_t mask;
262.239 + const uint32_t *pos;
262.240 +
262.241 + for (column = 0; column < columns; column++)
262.242 +
262.243 + for (row = 0, mask = 1 << (rows - 1);
262.244 + row < rows;
262.245 + row++, mask >>= 1)
262.246 + {
262.247 + /* Obtain the physical position. */
262.248 +
262.249 + pos = keypos[row][column];
262.250 +
262.251 + /* Obtain the width of the key. */
262.252 +
262.253 + colsize = (pos[2] * fbi.width) / WIDTH;
262.254 +
262.255 + /* Plot the rectangle for the key. */
262.256 +
262.257 + fill_rectangle((pos[0] * fbi.width) / WIDTH, pos[1] * rowsize, colsize, rowsize,
262.258 + keypad[column] & mask ? 0xffffff : 0);
262.259 + }
262.260 +
262.261 + /* Refresh the display. */
262.262 +
262.263 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height);
262.264 +}
262.265 +
262.266 +
262.267 +
262.268 +int main(void)
262.269 +{
262.270 + l4_cap_idx_t keypad_server;
262.271 + l4re_ds_t mem;
262.272 + l4_msgtag_t tag;
262.273 +
262.274 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
262.275 + return 1;
262.276 +
262.277 + if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
262.278 + return 1;
262.279 +
262.280 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
262.281 + return 1;
262.282 +
262.283 + /* Obtain a reference to the keypad. */
262.284 +
262.285 + keypad_server = l4re_env_get_cap("keypad");
262.286 + if (l4_is_invalid_cap(keypad_server)) return 1;
262.287 +
262.288 + /* Obtain a capability for the keypad data. */
262.289 +
262.290 + mem = l4re_util_cap_alloc();
262.291 + if (l4_is_invalid_cap(mem)) return 1;
262.292 +
262.293 + /* Obtain a reference to the keypad data. */
262.294 +
262.295 + l4_utcb_br()->bdr = 0;
262.296 + l4_utcb_br()->br[0] = L4_RCV_ITEM_SINGLE_CAP | mem;
262.297 +
262.298 + tag = l4_ipc_call(keypad_server, l4_utcb(),
262.299 + l4_msgtag(0, 0, 0, 0), /* label zero, zero words, zero *sent* items */
262.300 + L4_IPC_NEVER);
262.301 +
262.302 + if (l4_ipc_error(tag, l4_utcb())) return 1;
262.303 +
262.304 + /* Attach the keypad data to a region in this task. */
262.305 +
262.306 + if (l4re_rm_attach(&keymem, l4re_ds_size(mem), L4RE_RM_SEARCH_ADDR, mem, 0,
262.307 + L4_PAGESHIFT))
262.308 + return 1;
262.309 +
262.310 + /* Show the keypad state. */
262.311 +
262.312 + keypad = (uint32_t *) keymem;
262.313 +
262.314 + while (1) show_keypad();
262.315 +
262.316 + return 0;
262.317 +}
263.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
263.2 +++ b/pkg/landfall-examples/letux400_leds/Makefile Sun May 13 01:34:16 2018 +0200
263.3 @@ -0,0 +1,8 @@
263.4 +PKGDIR ?= ../..
263.5 +L4DIR ?= $(PKGDIR)/../..
263.6 +
263.7 +TARGET = ex_letux400_leds
263.8 +SRC_C = letux400_leds.c
263.9 +REQUIRES_LIBS = libio l4re_c-util libdrivers-gpio libdrivers-pwm
263.10 +
263.11 +include $(L4DIR)/mk/prog.mk
264.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
264.2 +++ b/pkg/landfall-examples/letux400_leds/letux400_leds.c Sun May 13 01:34:16 2018 +0200
264.3 @@ -0,0 +1,197 @@
264.4 +/*
264.5 + * Access the LED and PWM GPIOs on the Letux 400 notebook computer.
264.6 + * This example shows how to use the following GPIOs:
264.7 + *
264.8 + * PA27 - Caps Lock
264.9 + * PC22 - Num Lock
264.10 + * PC30 - PWM backlight
264.11 + *
264.12 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
264.13 + *
264.14 + * This program is free software; you can redistribute it and/or
264.15 + * modify it under the terms of the GNU General Public License as
264.16 + * published by the Free Software Foundation; either version 2 of
264.17 + * the License, or (at your option) any later version.
264.18 + *
264.19 + * This program is distributed in the hope that it will be useful,
264.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
264.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
264.22 + * GNU General Public License for more details.
264.23 + *
264.24 + * You should have received a copy of the GNU General Public License
264.25 + * along with this program; if not, write to the Free Software
264.26 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
264.27 + * Boston, MA 02110-1301, USA
264.28 + */
264.29 +
264.30 +#include <l4/devices/gpio-jz4730.h>
264.31 +#include <l4/devices/pwm-jz4730.h>
264.32 +
264.33 +#include <l4/io/io.h>
264.34 +#include <l4/re/env.h>
264.35 +#include <l4/re/c/util/cap_alloc.h>
264.36 +#include <l4/sys/factory.h>
264.37 +#include <l4/sys/ipc.h>
264.38 +#include <l4/util/util.h>
264.39 +#include <l4/vbus/vbus.h>
264.40 +
264.41 +#include <stdio.h>
264.42 +#include <stdint.h>
264.43 +#include <unistd.h>
264.44 +
264.45 +enum {
264.46 + CAPS = 27, // via PORTA
264.47 + NUM = 22, // via PORTC
264.48 + PWM = 30, // via PORTC
264.49 +};
264.50 +
264.51 +
264.52 +
264.53 +/* Device and resource discovery. */
264.54 +
264.55 +static char const *resource_type(enum l4io_resource_types_t type)
264.56 +{
264.57 + switch (type)
264.58 + {
264.59 + case L4VBUS_RESOURCE_INVALID:
264.60 + return "INVALID";
264.61 +
264.62 + case L4VBUS_RESOURCE_IRQ:
264.63 + return "IRQ";
264.64 +
264.65 + case L4VBUS_RESOURCE_MEM:
264.66 + return "MEMORY";
264.67 +
264.68 + default:
264.69 + return "OTHER";
264.70 + }
264.71 +}
264.72 +
264.73 +static int get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
264.74 +{
264.75 + int result = l4io_lookup_device(hid, dh, 0, rh);
264.76 +
264.77 + if (result < 0)
264.78 + printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");
264.79 +
264.80 + return result;
264.81 +}
264.82 +
264.83 +static int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
264.84 + enum l4io_resource_types_t type)
264.85 +{
264.86 + int current = 0, result = 0;
264.87 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
264.88 +
264.89 + do
264.90 + {
264.91 + result = l4vbus_get_resource(vbus, dh, current, res);
264.92 +
264.93 + if (result)
264.94 + printf("Could not access resource of type %s.\n", resource_type(type));
264.95 + else
264.96 + printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,
264.97 + resource_type(res->type), res->start, res->end);
264.98 +
264.99 + current++;
264.100 + }
264.101 + while ((!result) && (res->type != type));
264.102 +
264.103 + return result;
264.104 +}
264.105 +
264.106 +static int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
264.107 +{
264.108 + l4io_device_handle_t dh;
264.109 + l4io_resource_handle_t rh;
264.110 + l4io_resource_t res;
264.111 + int result;
264.112 +
264.113 + result = get_device(hid, &dh, &rh);
264.114 +
264.115 + if (result < 0)
264.116 + return result;
264.117 +
264.118 + result = get_resource(dh, &res, L4IO_RESOURCE_MEM);
264.119 +
264.120 + if (result)
264.121 + return result;
264.122 +
264.123 + if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,
264.124 + L4IO_MEM_NONCACHED, start)))
264.125 + {
264.126 + printf("Could not get address for '%s'.\n", hid);
264.127 + return result;
264.128 + }
264.129 +
264.130 + printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);
264.131 +
264.132 + *end = *start + (res.end - res.start + 1);
264.133 +
264.134 + return 0;
264.135 +}
264.136 +
264.137 +int main(void)
264.138 +{
264.139 + l4_addr_t gpio_base = 0, gpio_base_end = 0, port_a, port_a_end, port_c, port_c_end;
264.140 + l4_addr_t pwm_base = 0, pwm_base_end = 0;
264.141 + void *gpio_port_a, *gpio_port_c, *pwm0_device;
264.142 + int result = 0;
264.143 + int caps = 0, num = 1, pwm = 300, pwmdir = -50;
264.144 +
264.145 + /* Obtain resource details describing the I/O memory. */
264.146 +
264.147 + printf("Access GPIO...\n");
264.148 +
264.149 + if ((result = get_memory("jz4730-gpio", &gpio_base, &gpio_base_end)) < 0)
264.150 + return 1;
264.151 +
264.152 + port_a = gpio_base;
264.153 + port_a_end = port_a + 0x30;
264.154 + port_c = gpio_base + 0x60;
264.155 + port_c_end = port_c + 0x30;
264.156 +
264.157 + printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end);
264.158 + printf("PORTA at 0x%lx...0x%lx.\n", port_a, port_a_end);
264.159 + printf("PORTC at 0x%lx...0x%lx.\n", port_c, port_c_end);
264.160 +
264.161 + gpio_port_a = jz4730_gpio_init(port_a, port_a_end, 32);
264.162 + gpio_port_c = jz4730_gpio_init(port_c, port_c_end, 32);
264.163 +
264.164 + printf("Access PWM...\n");
264.165 +
264.166 + if ((result = get_memory("jz4730-pwm", &pwm_base, &pwm_base_end)) < 0)
264.167 + return 1;
264.168 +
264.169 + pwm0_device = jz4730_pwm_init(pwm_base, pwm_base + 0x1000);
264.170 +
264.171 + /* Set the GPIO pins up. */
264.172 +
264.173 + printf("Set up GPIO pins...\n");
264.174 +
264.175 + jz4730_gpio_setup(gpio_port_a, CAPS, Fix_output, caps);
264.176 + jz4730_gpio_setup(gpio_port_c, NUM, Fix_output, num);
264.177 + jz4730_gpio_config_pad(gpio_port_c, PWM, Function_alt, 1);
264.178 +
264.179 + /* Set the PWM device up. */
264.180 +
264.181 + printf("Set up PWM...\n");
264.182 +
264.183 + jz4730_pwm_set_duty(pwm0_device, pwm);
264.184 + jz4730_pwm_set_period(pwm0_device, 299);
264.185 + jz4730_pwm_set_control(pwm0_device, 0x80 | 0x3f);
264.186 +
264.187 + while (1)
264.188 + {
264.189 + caps = 1 - caps;
264.190 + jz4730_gpio_set(gpio_port_a, CAPS, caps);
264.191 + num = 1 - num;
264.192 + jz4730_gpio_set(gpio_port_c, NUM, num);
264.193 + pwm += pwmdir;
264.194 + jz4730_pwm_set_duty(pwm0_device, pwm);
264.195 + if (pwm == 0) pwmdir = 50; else if (pwm == 300) pwmdir = -50;
264.196 + l4_sleep(1000); // 1000ms
264.197 + }
264.198 +
264.199 + return 0;
264.200 +}
265.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
265.2 +++ b/pkg/landfall-examples/qi_lb60_backlight/Makefile Sun May 13 01:34:16 2018 +0200
265.3 @@ -0,0 +1,8 @@
265.4 +PKGDIR ?= ../..
265.5 +L4DIR ?= $(PKGDIR)/../..
265.6 +
265.7 +TARGET = ex_qi_lb60_backlight
265.8 +SRC_CC = qi_lb60_backlight.cc
265.9 +REQUIRES_LIBS = libio l4re_c-util libdevice-backlight-client libdevice-input-keypad libdrivers-keypad-qi_lb60
265.10 +
265.11 +include $(L4DIR)/mk/prog.mk
266.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
266.2 +++ b/pkg/landfall-examples/qi_lb60_backlight/qi_lb60_backlight.cc Sun May 13 01:34:16 2018 +0200
266.3 @@ -0,0 +1,109 @@
266.4 +/*
266.5 + * Access the keypad to modify the backlight on the Ben NanoNote.
266.6 + *
266.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
266.8 + *
266.9 + * This program is free software; you can redistribute it and/or
266.10 + * modify it under the terms of the GNU General Public License as
266.11 + * published by the Free Software Foundation; either version 2 of
266.12 + * the License, or (at your option) any later version.
266.13 + *
266.14 + * This program is distributed in the hope that it will be useful,
266.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
266.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
266.17 + * GNU General Public License for more details.
266.18 + *
266.19 + * You should have received a copy of the GNU General Public License
266.20 + * along with this program; if not, write to the Free Software
266.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
266.22 + * Boston, MA 02110-1301, USA
266.23 + */
266.24 +
266.25 +#include <l4/devices/backlight-client.h>
266.26 +#include <l4/devices/input-keypad-client.h>
266.27 +
266.28 +#include <l4/re/env>
266.29 +#include <l4/sys/capability>
266.30 +
266.31 +#include <l4/re/event_enums.h>
266.32 +#include <l4/util/util.h>
266.33 +
266.34 +/* Backlight level. */
266.35 +
266.36 +enum Qi_lb60_backlight_levels
266.37 +{
266.38 + Qi_lb60_backlight_min_level = 0,
266.39 + Qi_lb60_backlight_max_level = 255,
266.40 + Qi_lb60_backlight_step = 10,
266.41 +};
266.42 +
266.43 +static int backlight_level = 64;
266.44 +
266.45 +/* Key state. */
266.46 +
266.47 +static int modifier_set = 0;
266.48 +
266.49 +/* Backlight device abstractions. */
266.50 +
266.51 +static L4::Cap<Backlight_device_interface> backlight_device;
266.52 +
266.53 +
266.54 +
266.55 +/* Input event handler. */
266.56 +
266.57 +static void handler(Input_event event, void *priv)
266.58 +{
266.59 + (void) priv;
266.60 +
266.61 + /* Track the state of the modifier key. */
266.62 +
266.63 + if (event.code == L4RE_KEY_FN)
266.64 + modifier_set = event.value;
266.65 +
266.66 + if (!event.value || !modifier_set)
266.67 + return;
266.68 +
266.69 + /* Upon keypress events, test controls and update the backlight. */
266.70 +
266.71 + switch (event.code)
266.72 + {
266.73 + case L4RE_KEY_VOLUMEDOWN:
266.74 + if (backlight_level < Qi_lb60_backlight_min_level + Qi_lb60_backlight_step)
266.75 + backlight_level = Qi_lb60_backlight_min_level;
266.76 + else
266.77 + backlight_level -= Qi_lb60_backlight_step;
266.78 + break;
266.79 +
266.80 + case L4RE_KEY_VOLUMEUP:
266.81 + if (backlight_level > Qi_lb60_backlight_max_level - Qi_lb60_backlight_step)
266.82 + backlight_level = Qi_lb60_backlight_max_level;
266.83 + else
266.84 + backlight_level += Qi_lb60_backlight_step;
266.85 + break;
266.86 +
266.87 + default: return;
266.88 + }
266.89 +
266.90 + /* Use the backlight device to update the backlight level. */
266.91 +
266.92 + backlight_device->set_brightness(backlight_level);
266.93 +}
266.94 +
266.95 +
266.96 +
266.97 +int main(void)
266.98 +{
266.99 + Keypad *keypad = Keypad::get_keypad();
266.100 + Input_keypad_client client(keypad);
266.101 +
266.102 + /* Obtain a reference to the backlight device. */
266.103 +
266.104 + backlight_device = L4Re::Env::env()->get_cap<Backlight_device_interface>("backlight");
266.105 + if (!backlight_device.is_valid()) return 1;
266.106 +
266.107 + client.attach(handler, 0);
266.108 +
266.109 + l4_sleep_forever();
266.110 +
266.111 + return 0;
266.112 +}
267.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
267.2 +++ b/pkg/landfall-examples/qi_lb60_keypad/Makefile Sun May 13 01:34:16 2018 +0200
267.3 @@ -0,0 +1,8 @@
267.4 +PKGDIR ?= ../..
267.5 +L4DIR ?= $(PKGDIR)/../..
267.6 +
267.7 +TARGET = ex_qi_lb60_keypad
267.8 +SRC_C = qi_lb60_keypad.c memory.c
267.9 +REQUIRES_LIBS = libio l4re_c-util libdrivers-gpio
267.10 +
267.11 +include $(L4DIR)/mk/prog.mk
268.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
268.2 +++ b/pkg/landfall-examples/qi_lb60_keypad/memory.c Sun May 13 01:34:16 2018 +0200
268.3 @@ -0,0 +1,78 @@
268.4 +/*
268.5 + * Memory allocation utility functions.
268.6 + *
268.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
268.8 + *
268.9 + * This program is free software; you can redistribute it and/or
268.10 + * modify it under the terms of the GNU General Public License as
268.11 + * published by the Free Software Foundation; either version 2 of
268.12 + * the License, or (at your option) any later version.
268.13 + *
268.14 + * This program is distributed in the hope that it will be useful,
268.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
268.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
268.17 + * GNU General Public License for more details.
268.18 + *
268.19 + * You should have received a copy of the GNU General Public License
268.20 + * along with this program; if not, write to the Free Software
268.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
268.22 + * Boston, MA 02110-1301, USA
268.23 + */
268.24 +
268.25 +#include <l4/io/io.h>
268.26 +#include <l4/re/env.h>
268.27 +#include <l4/re/c/mem_alloc.h>
268.28 +#include <l4/re/c/util/cap_alloc.h>
268.29 +#include <l4/util/util.h>
268.30 +#include <l4/vbus/vbus.h>
268.31 +
268.32 +#include "memory.h"
268.33 +
268.34 +int get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
268.35 +{
268.36 + return l4io_lookup_device(hid, dh, 0, rh);
268.37 +}
268.38 +
268.39 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
268.40 + enum l4io_resource_types_t type)
268.41 +{
268.42 + int current = 0, result = 0;
268.43 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
268.44 +
268.45 + do
268.46 + {
268.47 + result = l4vbus_get_resource(vbus, dh, current, res);
268.48 + current++;
268.49 + }
268.50 + while ((!result) && (res->type != type));
268.51 +
268.52 + return result;
268.53 +}
268.54 +
268.55 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
268.56 +{
268.57 + l4io_device_handle_t dh;
268.58 + l4io_resource_handle_t rh;
268.59 + l4io_resource_t res;
268.60 + int result;
268.61 +
268.62 + result = get_device(hid, &dh, &rh);
268.63 +
268.64 + if (result < 0)
268.65 + return result;
268.66 +
268.67 + result = get_resource(dh, &res, L4IO_RESOURCE_MEM);
268.68 +
268.69 + if (result)
268.70 + return result;
268.71 +
268.72 + result = l4io_request_iomem(res.start, res.end - res.start + 1,
268.73 + L4IO_MEM_NONCACHED, start);
268.74 +
268.75 + if (result)
268.76 + return result;
268.77 +
268.78 + *end = *start + (res.end - res.start + 1);
268.79 +
268.80 + return 0;
268.81 +}
269.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
269.2 +++ b/pkg/landfall-examples/qi_lb60_keypad/memory.h Sun May 13 01:34:16 2018 +0200
269.3 @@ -0,0 +1,36 @@
269.4 +/*
269.5 + * Memory allocation utility functions.
269.6 + *
269.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
269.8 + *
269.9 + * This program is free software; you can redistribute it and/or
269.10 + * modify it under the terms of the GNU General Public License as
269.11 + * published by the Free Software Foundation; either version 2 of
269.12 + * the License, or (at your option) any later version.
269.13 + *
269.14 + * This program is distributed in the hope that it will be useful,
269.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
269.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
269.17 + * GNU General Public License for more details.
269.18 + *
269.19 + * You should have received a copy of the GNU General Public License
269.20 + * along with this program; if not, write to the Free Software
269.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
269.22 + * Boston, MA 02110-1301, USA
269.23 + */
269.24 +
269.25 +#ifndef __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__
269.26 +#define __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__
269.27 +
269.28 +#include <l4/io/io.h>
269.29 +#include <l4/sys/types.h>
269.30 +
269.31 +int get_device(char const *hid, l4io_device_handle_t *dh,
269.32 + l4io_resource_handle_t *rh);
269.33 +
269.34 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
269.35 + enum l4io_resource_types_t type);
269.36 +
269.37 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end);
269.38 +
269.39 +#endif /* __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__ */
270.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
270.2 +++ b/pkg/landfall-examples/qi_lb60_keypad/qi_lb60_keypad.c Sun May 13 01:34:16 2018 +0200
270.3 @@ -0,0 +1,203 @@
270.4 +/*
270.5 + * Access the keypad GPIOs on the Ben NanoNote.
270.6 + *
270.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
270.8 + *
270.9 + * This program is free software; you can redistribute it and/or
270.10 + * modify it under the terms of the GNU General Public License as
270.11 + * published by the Free Software Foundation; either version 2 of
270.12 + * the License, or (at your option) any later version.
270.13 + *
270.14 + * This program is distributed in the hope that it will be useful,
270.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
270.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
270.17 + * GNU General Public License for more details.
270.18 + *
270.19 + * You should have received a copy of the GNU General Public License
270.20 + * along with this program; if not, write to the Free Software
270.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
270.22 + * Boston, MA 02110-1301, USA
270.23 + */
270.24 +
270.25 +#include <l4/devices/gpio-jz4740.h>
270.26 +#include <l4/re/c/util/video/goos_fb.h>
270.27 +#include <l4/re/c/video/view.h>
270.28 +#include <l4/util/util.h>
270.29 +
270.30 +#include <stdio.h>
270.31 +#include <unistd.h>
270.32 +#include <stdint.h>
270.33 +
270.34 +#include "memory.h"
270.35 +
270.36 +enum Jz4740_keypad_gpio
270.37 +{
270.38 + Jz4740_keypad_gpio_inputs_count = 8,
270.39 + Jz4740_keypad_gpio_outputs_count = 8,
270.40 +};
270.41 +
270.42 +/* Port D input pins. */
270.43 +
270.44 +const uint8_t Jz4740_keypad_inputs[Jz4740_keypad_gpio_inputs_count] = {
270.45 + 18, 19, 20, 21, 22, 23, 24, 26
270.46 +};
270.47 +
270.48 +const Pin_slice Jz4740_keypad_inputs_mask = {.mask = 0x05fc0000, .offset = 0};
270.49 +
270.50 +/* Port C output pins. */
270.51 +
270.52 +const uint8_t Jz4740_keypad_outputs[Jz4740_keypad_gpio_outputs_count] = {
270.53 + 10, 11, 12, 13, 14, 15, 16, 17
270.54 +};
270.55 +
270.56 +const Pin_slice Jz4740_keypad_outputs_mask = {.mask = 0x0003fc00, .offset = 0};
270.57 +
270.58 +/* Video abstractions. */
270.59 +
270.60 +static l4re_util_video_goos_fb_t gfb;
270.61 +static l4re_video_view_info_t fbi;
270.62 +static void *fb;
270.63 +
270.64 +/* Peripheral memory regions. */
270.65 +
270.66 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
270.67 +
270.68 +/* GPIO abstractions. */
270.69 +
270.70 +static void *gpio_port_c, *gpio_port_d;
270.71 +
270.72 +/* Keypad status. */
270.73 +
270.74 +uint8_t keypad[Jz4740_keypad_gpio_outputs_count];
270.75 +
270.76 +
270.77 +
270.78 +/* Initialise the pins for scanning the keypad. */
270.79 +
270.80 +static void init_keyscan(void)
270.81 +{
270.82 + jz4740_gpio_multi_setup(gpio_port_d, &Jz4740_keypad_inputs_mask, Fix_input, 0);
270.83 + jz4740_gpio_multi_config_pull(gpio_port_d, &Jz4740_keypad_inputs_mask, Pull_up);
270.84 + jz4740_gpio_multi_setup(gpio_port_c, &Jz4740_keypad_outputs_mask, Fix_input, 0);
270.85 +}
270.86 +
270.87 +/*
270.88 +Scan the keypad by enabling each output column and inspecting each input row.
270.89 +Store each column bitmap in the keypad array.
270.90 +*/
270.91 +
270.92 +static void scan_keypad(void)
270.93 +{
270.94 + uint8_t column, row, value;
270.95 +
270.96 + for (column = 0; column < Jz4740_keypad_gpio_outputs_count; column++)
270.97 + {
270.98 + jz4740_gpio_setup(gpio_port_c, Jz4740_keypad_outputs[column], Fix_output, 0);
270.99 + l4_sleep(1);
270.100 +
270.101 + value = 0;
270.102 +
270.103 + for (row = 0; row < Jz4740_keypad_gpio_inputs_count; row++)
270.104 + value = (value << 1) | (jz4740_gpio_get(gpio_port_d, Jz4740_keypad_inputs[row]) ? 0 : 1);
270.105 +
270.106 + keypad[column] = value;
270.107 +
270.108 + jz4740_gpio_setup(gpio_port_c, Jz4740_keypad_outputs[column], Fix_input, 0);
270.109 + }
270.110 +}
270.111 +
270.112 +static uint32_t bitmask(uint32_t size)
270.113 +{
270.114 + return (1 << size) - 1;
270.115 +}
270.116 +
270.117 +static uint32_t truncate_channel(uint32_t value, uint32_t size)
270.118 +{
270.119 + return (value >> (8 - size)) & bitmask(size);
270.120 +}
270.121 +
270.122 +static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value)
270.123 +{
270.124 + if (bpp <= 8) *(uint8_t *) pos = value;
270.125 + else if (bpp <= 16) *(uint16_t *) pos = value;
270.126 + else *(uint32_t *) pos = value;
270.127 +}
270.128 +
270.129 +/* Show the state of a key on the display. */
270.130 +
270.131 +static void show_keystate(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb)
270.132 +{
270.133 + uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
270.134 + uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel;
270.135 + uint32_t bytes_per_line = fbi.bytes_per_line;
270.136 + uint32_t pos;
270.137 + uint32_t col, row;
270.138 +
270.139 + rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) |
270.140 + (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) |
270.141 + (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift);
270.142 +
270.143 + for (row = 0; row < h; row++)
270.144 + {
270.145 + pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel;
270.146 +
270.147 + for (col = 0; col < w; col++)
270.148 + {
270.149 + set_pixel(pos, bpp, rgb);
270.150 + pos += bytes_per_pixel;
270.151 + }
270.152 + }
270.153 +}
270.154 +
270.155 +/* Show the keypad status on the display. */
270.156 +
270.157 +static void show_keypad(void)
270.158 +{
270.159 + uint32_t colsize = fbi.width / Jz4740_keypad_gpio_outputs_count,
270.160 + rowsize = fbi.height / Jz4740_keypad_gpio_inputs_count;
270.161 + uint8_t column, row;
270.162 + uint32_t mask;
270.163 +
270.164 + for (column = 0; column < Jz4740_keypad_gpio_outputs_count; column++)
270.165 +
270.166 + for (row = 0, mask = 1 << (Jz4740_keypad_gpio_inputs_count - 1);
270.167 + row < Jz4740_keypad_gpio_inputs_count;
270.168 + row++, mask >>= 1)
270.169 +
270.170 + show_keystate(column * colsize, row * rowsize, colsize, rowsize,
270.171 + keypad[column] & mask ? 0xffffff : 0);
270.172 +
270.173 + /* Refresh the display. */
270.174 +
270.175 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height);
270.176 +}
270.177 +
270.178 +int main(void)
270.179 +{
270.180 + int result;
270.181 +
270.182 + if ((result = get_memory("jz4740-gpio", &gpio_virt_base, &gpio_virt_base_end)) < 0)
270.183 + return 1;
270.184 +
270.185 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
270.186 + return 1;
270.187 +
270.188 + if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
270.189 + return 1;
270.190 +
270.191 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
270.192 + return 1;
270.193 +
270.194 + gpio_port_c = jz4740_gpio_init(gpio_virt_base + 0x200, gpio_virt_base + 0x300, 32);
270.195 + gpio_port_d = jz4740_gpio_init(gpio_virt_base + 0x300, gpio_virt_base + 0x400, 32);
270.196 +
270.197 + init_keyscan();
270.198 +
270.199 + while (1)
270.200 + {
270.201 + scan_keypad();
270.202 + show_keypad();
270.203 + }
270.204 +
270.205 + return 0;
270.206 +}
271.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
271.2 +++ b/pkg/landfall-examples/qi_lb60_keypad_driver/Makefile Sun May 13 01:34:16 2018 +0200
271.3 @@ -0,0 +1,9 @@
271.4 +PKGDIR ?= ../..
271.5 +L4DIR ?= $(PKGDIR)/../..
271.6 +
271.7 +TARGET = ex_qi_lb60_keypad_driver
271.8 +SRC_CC = qi_lb60_keypad_driver.cc
271.9 +SRC_DATA = unifont.tff
271.10 +REQUIRES_LIBS = libio l4re_c-util libdevice-input-keypad libdrivers-keypad-qi_lb60 mag-gfx
271.11 +
271.12 +include $(L4DIR)/mk/prog.mk
272.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
272.2 +++ b/pkg/landfall-examples/qi_lb60_keypad_driver/qi_lb60_keypad_driver.cc Sun May 13 01:34:16 2018 +0200
272.3 @@ -0,0 +1,251 @@
272.4 +/*
272.5 + * Access the keypad on the configured device using an input driver.
272.6 + *
272.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
272.8 + *
272.9 + * This program is free software; you can redistribute it and/or
272.10 + * modify it under the terms of the GNU General Public License as
272.11 + * published by the Free Software Foundation; either version 2 of
272.12 + * the License, or (at your option) any later version.
272.13 + *
272.14 + * This program is distributed in the hope that it will be useful,
272.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
272.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
272.17 + * GNU General Public License for more details.
272.18 + *
272.19 + * You should have received a copy of the GNU General Public License
272.20 + * along with this program; if not, write to the Free Software
272.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
272.22 + * Boston, MA 02110-1301, USA
272.23 + *
272.24 + *
272.25 + * Font definitions and licence (see unifont.tff for bitmap data derived from
272.26 + * GNU Unifont's unifont.hex file):
272.27 + *
272.28 + * Copyright (C) 1998-2003 Roman Czyborra (http://czyborra.com/)
272.29 + *
272.30 + * All glyphs are released under the GNU General Public License
272.31 + * (GPL) version 2 or (at your option) a later version, with the
272.32 + * GNU font embedding exception:
272.33 + *
272.34 + * ** GPL v2.0 license with font embedding exception:
272.35 + *
272.36 + * As a special exception, if you create a document which
272.37 + * uses this font, and embed this font or unaltered portions
272.38 + * of this font into the document, this font does not by
272.39 + * itself cause the resulting document to be covered by
272.40 + * the GNU General Public License. This exception does not
272.41 + * however invalidate any other reasons why the document
272.42 + * might be covered by the GNU General Public License.
272.43 + * If you modify this font, you may extend this exception
272.44 + * to your version of the font, but you are not obligated
272.45 + * to do so. If you do not wish to do so, delete this
272.46 + * exception statement from your version.
272.47 + */
272.48 +
272.49 +#include <l4/devices/input-keypad-client.h>
272.50 +
272.51 +#include <l4/re/c/util/video/goos_fb.h>
272.52 +#include <l4/re/c/video/view.h>
272.53 +#include <l4/util/util.h>
272.54 +
272.55 +#include <l4/mag-gfx/canvas>
272.56 +#include <l4/mag-gfx/font>
272.57 +#include <l4/mag-gfx/geometry>
272.58 +#include <l4/mag-gfx/gfx_colors>
272.59 +#include <l4/mag-gfx/mem_factory>
272.60 +
272.61 +#include <stdint.h>
272.62 +#include <string.h>
272.63 +
272.64 +/* Video abstractions. */
272.65 +
272.66 +static l4re_util_video_goos_fb_t gfb;
272.67 +static l4re_video_view_info_t view_info;
272.68 +static void *fb = 0;
272.69 +
272.70 +/* Bundled font data. */
272.71 +
272.72 +extern char const _binary_unifont_tff_start[];
272.73 +
272.74 +/* Screen abstractions. */
272.75 +
272.76 +using namespace Mag_gfx;
272.77 +
272.78 +static Font *_font = 0;
272.79 +static Canvas *_screen = 0;
272.80 +
272.81 +
272.82 +
272.83 +/* Factories for certain pixel formats. */
272.84 +
272.85 +static Mem::Factory<Rgb16> _rgb16;
272.86 +static Mem::Factory<Rgb32> _rgb32;
272.87 +
272.88 +
272.89 +
272.90 +/* Key to character conversion function. */
272.91 +
272.92 +static const char *keys_to_strings[] = {
272.93 +
272.94 + 0, "Escape", "1", "2", "3", "4", "5", "6", "7", "8",
272.95 +
272.96 + "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E", "R",
272.97 +
272.98 + "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Left Ctrl",
272.99 +
272.100 + "A", "S", "D", "F", "G", "H", "J", "K", "L", ";",
272.101 +
272.102 + "'", "`", "Left Shift", "\\", "Z", "X", "C", "V", "B", "N",
272.103 +
272.104 + "M", ",", ".", "/", "Right Shift", "Keypad *", "Left Alt", "Space",
272.105 + "Caps Lock", "F1",
272.106 +
272.107 + "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "Num Lock",
272.108 +
272.109 + "Scroll Lock", "Keypad 7", "Keypad 8", "Keypad 9", "Keypad -", "Keypad 4",
272.110 + "Keypad 5", "Keypad 6", "Keypad +", "Keypad 1",
272.111 +
272.112 + "Keypad 2", "Keypad 3", "Keypad 0", "Keypad .", 0, 0, "#102", "F11", "F12", 0,
272.113 +
272.114 + 0, 0, 0, 0, 0, 0, "Keypad Enter", "Right Ctrl", "Keypad /", "SysRq",
272.115 +
272.116 + "Right Alt", "Line Feed", "Home", "Up", "Page Up", "Left", "Right", "End",
272.117 + "Down", "Page Down",
272.118 +
272.119 + "Insert", "Delete", "Macro", "Mute", "Volume Down", "Volume Up", "Power",
272.120 + "Keypad =", "Keypad +-", "Pause",
272.121 +};
272.122 +
272.123 +static const char null_string[] = "Unknown";
272.124 +
272.125 +const int keys_to_strings_length = 120;
272.126 +
272.127 +static const char *key_to_string(int key)
272.128 +{
272.129 + return key < keys_to_strings_length ? keys_to_strings[key] : 0;
272.130 +}
272.131 +
272.132 +/* Show the keypad event status on the display. */
272.133 +
272.134 +static uint8_t row = 0;
272.135 +static uint32_t text_x = 0, text_y = 0, next_y = 0;
272.136 +
272.137 +static void handler(Input_event event, void *priv)
272.138 +{
272.139 + uint32_t colsize = view_info.width / 10,
272.140 + rowsize = view_info.height / 20;
272.141 + uint8_t column;
272.142 + uint16_t mask;
272.143 +
272.144 + /* Convert the key code into a bit pattern. */
272.145 +
272.146 + if (!priv)
272.147 + {
272.148 + for (column = 0, mask = (1 << 9); column < 10; column++, mask >>= 1)
272.149 + _screen->draw_box(Rect(Point(column * colsize, row * rowsize), Area(colsize, rowsize)),
272.150 + event.code & mask ? event.value ? Rgb32::Color(0, 255, 0) : Rgb32::Color(255, 0, 0)
272.151 + : Rgb32::Color(0, 0, 0));
272.152 +
272.153 + /* Advance to the next row, wrapping around. */
272.154 +
272.155 + row = (row + 1) % 20;
272.156 + }
272.157 +
272.158 + /* Or produce a string. */
272.159 +
272.160 + else if (event.value)
272.161 + {
272.162 + const char *s = ((const char *(*)(int)) priv)(event.code);
272.163 + Rgba32::Color col;
272.164 +
272.165 + if (!s)
272.166 + {
272.167 + s = null_string;
272.168 + col = Rgba32::Color(255, 0, 0, Rgba32::Color::Amax);
272.169 + }
272.170 + else
272.171 + col = Rgba32::Color(255, 255, 255, Rgba32::Color::Amax);
272.172 +
272.173 + Area box = _font->str_sz(s, strlen(s));
272.174 +
272.175 + /* Test for enough space horizontally. */
272.176 +
272.177 + if (text_x + box.w() > view_info.width)
272.178 + {
272.179 + text_x = 0;
272.180 + text_y = next_y;
272.181 + next_y = text_y + box.h();
272.182 + }
272.183 +
272.184 + /* Expand the line height, if appropriate. */
272.185 +
272.186 + else if (text_y + box.h() > next_y)
272.187 + next_y += box.h();
272.188 +
272.189 + /* Test for enough space vertically. */
272.190 +
272.191 + if (next_y > view_info.height)
272.192 + {
272.193 + text_x = 0;
272.194 + text_y = 0;
272.195 + next_y = box.h();
272.196 + }
272.197 +
272.198 + Point p(text_x, text_y);
272.199 +
272.200 + _screen->draw_box(Rect(p, box), Rgb32::Color(0, 0, 0));
272.201 + _screen->draw_string(p, _font, col, s, strlen(s));
272.202 +
272.203 + /* Move to the next position. */
272.204 +
272.205 + text_x += box.w();
272.206 + }
272.207 +
272.208 + /* Refresh the display. */
272.209 +
272.210 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, view_info.width, view_info.height);
272.211 +}
272.212 +
272.213 +/* Arguments: [ chars ] */
272.214 +
272.215 +int main(int argc, char *argv[])
272.216 +{
272.217 + Keypad *keypad = Keypad::get_keypad();
272.218 + Input_keypad_client client(keypad);
272.219 +
272.220 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
272.221 + return 1;
272.222 +
272.223 + if (l4re_util_video_goos_fb_view_info(&gfb, &view_info))
272.224 + return 1;
272.225 +
272.226 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
272.227 + return 1;
272.228 +
272.229 + /* Obtain a canvas for the framebuffer. */
272.230 +
272.231 + Factory *factory;
272.232 +
272.233 + if (view_info.pixel_info.bytes_per_pixel == 2)
272.234 + factory = &_rgb16;
272.235 + else
272.236 + factory = &_rgb32;
272.237 +
272.238 + Canvas *screen = factory->create_canvas((void *) ((unsigned long) fb + view_info.buffer_offset),
272.239 + Area(view_info.width, view_info.height),
272.240 + view_info.bytes_per_line);
272.241 +
272.242 + Font font(&_binary_unifont_tff_start[0]);
272.243 +
272.244 + _screen = screen;
272.245 + _font = &font;
272.246 +
272.247 + /* Attach the event handler and wait for events. */
272.248 +
272.249 + client.attach(handler, (argc > 1) && (!strcmp(argv[1], "chars")) ? (void *) key_to_string : 0);
272.250 +
272.251 + l4_sleep_forever();
272.252 +
272.253 + return 0;
272.254 +}
273.1 Binary file pkg/landfall-examples/qi_lb60_keypad_driver/unifont.tff has changed
274.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
274.2 +++ b/pkg/landfall-examples/qi_lb60_keypad_physical/Makefile Sun May 13 01:34:16 2018 +0200
274.3 @@ -0,0 +1,8 @@
274.4 +PKGDIR ?= ../..
274.5 +L4DIR ?= $(PKGDIR)/../..
274.6 +
274.7 +TARGET = ex_qi_lb60_keypad_physical
274.8 +SRC_C = qi_lb60_keypad_physical.c
274.9 +REQUIRES_LIBS = l4re_c-util
274.10 +
274.11 +include $(L4DIR)/mk/prog.mk
275.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
275.2 +++ b/pkg/landfall-examples/qi_lb60_keypad_physical/qi_lb60_keypad_physical.c Sun May 13 01:34:16 2018 +0200
275.3 @@ -0,0 +1,308 @@
275.4 +/*
275.5 + * Display the physical keypad matrix layout for the Ben NanoNote.
275.6 + *
275.7 + * (c) 2018 Paul Boddie <paul@boddie.org.uk>
275.8 + *
275.9 + * This program is free software; you can redistribute it and/or
275.10 + * modify it under the terms of the GNU General Public License as
275.11 + * published by the Free Software Foundation; either version 2 of
275.12 + * the License, or (at your option) any later version.
275.13 + *
275.14 + * This program is distributed in the hope that it will be useful,
275.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
275.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
275.17 + * GNU General Public License for more details.
275.18 + *
275.19 + * You should have received a copy of the GNU General Public License
275.20 + * along with this program; if not, write to the Free Software
275.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
275.22 + * Boston, MA 02110-1301, USA
275.23 + */
275.24 +
275.25 +#include <l4/re/c/rm.h>
275.26 +#include <l4/re/c/util/cap_alloc.h>
275.27 +#include <l4/re/env.h>
275.28 +#include <l4/util/util.h>
275.29 +#include <l4/sys/ipc.h>
275.30 +
275.31 +#include <l4/re/c/util/video/goos_fb.h>
275.32 +#include <l4/re/c/video/view.h>
275.33 +
275.34 +#include <l4/util/util.h>
275.35 +#include <stdio.h>
275.36 +#include <unistd.h>
275.37 +#include <stdint.h>
275.38 +#include <stdlib.h>
275.39 +
275.40 +enum Jz4740_keypad_gpio
275.41 +{
275.42 + Jz4740_keypad_gpio_inputs_count = 8,
275.43 + Jz4740_keypad_gpio_outputs_count = 8,
275.44 +};
275.45 +
275.46 +/* Video abstractions. */
275.47 +
275.48 +static l4re_util_video_goos_fb_t gfb;
275.49 +static l4re_video_view_info_t fbi;
275.50 +static void *fb;
275.51 +
275.52 +/* Keypad status and dimensions. */
275.53 +
275.54 +uint32_t *keypad = 0;
275.55 +void *keymem = 0;
275.56 +int columns = Jz4740_keypad_gpio_outputs_count, rows = Jz4740_keypad_gpio_inputs_count;
275.57 +
275.58 +/* Position units. */
275.59 +
275.60 +enum {
275.61 + KEY = 12, DIRKEY = 8,
275.62 + WIDTH = 120, HEIGHT = 72, ROWS = 6,
275.63 +};
275.64 +
275.65 +/*
275.66 + F1 F2 F3 F4 F5 F6 F7 F8
275.67 +Q W E R T Y U I O P
275.68 +A S D F G H J K L Bsp
275.69 +Esc Z X C V B N M = Enter
275.70 +Tab Cap \ ' , . / Up V-Up
275.71 +LSh LAl Fn Sym Spc Qi Ctr Lt Dn Rt V-Dn
275.72 +*/
275.73 +
275.74 +enum {
275.75 + SIZE_KEY_F1 = KEY, SIZE_KEY_F2 = KEY, SIZE_KEY_F3 = KEY, SIZE_KEY_F4 = KEY,
275.76 + SIZE_KEY_F5 = KEY, SIZE_KEY_F6 = KEY, SIZE_KEY_F7 = KEY, SIZE_KEY_F8 = KEY,
275.77 +
275.78 + SIZE_KEY_Q = KEY, SIZE_KEY_W = KEY, SIZE_KEY_E = KEY, SIZE_KEY_R = KEY,
275.79 + SIZE_KEY_T = KEY, SIZE_KEY_Y = KEY, SIZE_KEY_U = KEY, SIZE_KEY_I = KEY,
275.80 + SIZE_KEY_O = KEY, SIZE_KEY_P = KEY,
275.81 +
275.82 + SIZE_KEY_A = KEY, SIZE_KEY_S = KEY, SIZE_KEY_D = KEY, SIZE_KEY_F = KEY,
275.83 + SIZE_KEY_G = KEY, SIZE_KEY_H = KEY, SIZE_KEY_J = KEY, SIZE_KEY_K = KEY,
275.84 + SIZE_KEY_L = KEY, SIZE_KEY_BACKSPACE = KEY,
275.85 +
275.86 + SIZE_KEY_ESCAPE = KEY, SIZE_KEY_Z = KEY, SIZE_KEY_X = KEY, SIZE_KEY_C = KEY,
275.87 + SIZE_KEY_V = KEY, SIZE_KEY_B = KEY, SIZE_KEY_N = KEY, SIZE_KEY_M = KEY,
275.88 + SIZE_KEY_EQUAL = KEY, SIZE_KEY_ENTER = KEY,
275.89 +
275.90 + SIZE_KEY_TAB = KEY, SIZE_KEY_DOWNSHIFT = KEY, SIZE_KEY_BACKSLASH = KEY, SIZE_KEY_APOSTROPHE = KEY,
275.91 + SIZE_KEY_COMMA = KEY, SIZE_KEY_DOT = KEY, SIZE_KEY_SLASH = KEY,
275.92 + SIZE_KEY_UP = DIRKEY, SIZE_KEY_VOLUMEUP = KEY,
275.93 +
275.94 + SIZE_KEY_LEFTSHIFT = KEY, SIZE_KEY_LEFTALT = KEY, SIZE_KEY_FN = KEY, SIZE_KEY_SYM = KEY,
275.95 + SIZE_KEY_SPACE = KEY, SIZE_KEY_QI = KEY, SIZE_KEY_RIGHTCTRL = KEY, SIZE_KEY_LEFT = DIRKEY,
275.96 + SIZE_KEY_DOWN = DIRKEY, SIZE_KEY_RIGHT = DIRKEY, SIZE_KEY_VOLUMEDOWN = KEY,
275.97 +};
275.98 +
275.99 +enum {
275.100 + XPOS_KEY_F1 = 2*KEY, XPOS_KEY_F2 = 3*KEY, XPOS_KEY_F3 = 4*KEY, XPOS_KEY_F4 = 5*KEY,
275.101 + XPOS_KEY_F5 = 6*KEY, XPOS_KEY_F6 = 7*KEY, XPOS_KEY_F7 = 8*KEY, XPOS_KEY_F8 = 9*KEY,
275.102 +
275.103 + XPOS_KEY_Q = 0, XPOS_KEY_W = KEY, XPOS_KEY_E = 2*KEY, XPOS_KEY_R = 3*KEY,
275.104 + XPOS_KEY_T = 4*KEY, XPOS_KEY_Y = 5*KEY, XPOS_KEY_U = 6*KEY, XPOS_KEY_I = 7*KEY,
275.105 + XPOS_KEY_O = 8*KEY, XPOS_KEY_P = 9*KEY,
275.106 +
275.107 + XPOS_KEY_A = 0, XPOS_KEY_S = KEY, XPOS_KEY_D = 2*KEY, XPOS_KEY_F = 3*KEY,
275.108 + XPOS_KEY_G = 4*KEY, XPOS_KEY_H = 5*KEY, XPOS_KEY_J = 6*KEY, XPOS_KEY_K = 7*KEY,
275.109 + XPOS_KEY_L = 8*KEY, XPOS_KEY_BACKSPACE = 9*KEY,
275.110 +
275.111 + XPOS_KEY_ESCAPE = 0, XPOS_KEY_Z = KEY, XPOS_KEY_X = 2*KEY, XPOS_KEY_C = 3*KEY,
275.112 + XPOS_KEY_V = 4*KEY, XPOS_KEY_B = 5*KEY, XPOS_KEY_N = 6*KEY, XPOS_KEY_M = 7*KEY,
275.113 + XPOS_KEY_EQUAL = 8*KEY, XPOS_KEY_ENTER = 9*KEY,
275.114 +
275.115 + XPOS_KEY_TAB = 0, XPOS_KEY_DOWNSHIFT = KEY, XPOS_KEY_BACKSLASH = 2*KEY, XPOS_KEY_APOSTROPHE = 3*KEY,
275.116 + XPOS_KEY_COMMA = 4*KEY, XPOS_KEY_DOT = 5*KEY, XPOS_KEY_SLASH = 6*KEY,
275.117 + XPOS_KEY_UP = 7*KEY+DIRKEY, XPOS_KEY_VOLUMEUP = 9*KEY,
275.118 +
275.119 + XPOS_KEY_LEFTSHIFT = 0, XPOS_KEY_LEFTALT = KEY, XPOS_KEY_FN = 2*KEY, XPOS_KEY_SYM = 3*KEY,
275.120 + XPOS_KEY_SPACE = 4*KEY, XPOS_KEY_QI = 5*KEY, XPOS_KEY_RIGHTCTRL = 6*KEY, XPOS_KEY_LEFT = 7*KEY,
275.121 + XPOS_KEY_DOWN = 7*KEY+DIRKEY, XPOS_KEY_RIGHT = 7*KEY+2*DIRKEY, XPOS_KEY_VOLUMEDOWN = 9*KEY,
275.122 +};
275.123 +
275.124 +enum {
275.125 + YPOS_KEY_F1 = 0, YPOS_KEY_F2 = 0, YPOS_KEY_F3 = 0, YPOS_KEY_F4 = 0,
275.126 + YPOS_KEY_F5 = 0, YPOS_KEY_F6 = 0, YPOS_KEY_F7 = 0, YPOS_KEY_F8 = 0,
275.127 +
275.128 + YPOS_KEY_Q = 1, YPOS_KEY_W = 1, YPOS_KEY_E = 1, YPOS_KEY_R = 1,
275.129 + YPOS_KEY_T = 1, YPOS_KEY_Y = 1, YPOS_KEY_U = 1, YPOS_KEY_I = 1,
275.130 + YPOS_KEY_O = 1, YPOS_KEY_P = 1,
275.131 +
275.132 + YPOS_KEY_A = 2, YPOS_KEY_S = 2, YPOS_KEY_D = 2, YPOS_KEY_F = 2,
275.133 + YPOS_KEY_G = 2, YPOS_KEY_H = 2, YPOS_KEY_J = 2, YPOS_KEY_K = 2,
275.134 + YPOS_KEY_L = 2, YPOS_KEY_BACKSPACE = 2,
275.135 +
275.136 + YPOS_KEY_ESCAPE = 3, YPOS_KEY_Z = 3, YPOS_KEY_X = 3, YPOS_KEY_C = 3,
275.137 + YPOS_KEY_V = 3, YPOS_KEY_B = 3, YPOS_KEY_N = 3, YPOS_KEY_M = 3,
275.138 + YPOS_KEY_EQUAL = 3, YPOS_KEY_ENTER = 3,
275.139 +
275.140 + YPOS_KEY_TAB = 4, YPOS_KEY_DOWNSHIFT = 4, YPOS_KEY_BACKSLASH = 4, YPOS_KEY_APOSTROPHE = 4,
275.141 + YPOS_KEY_COMMA = 4, YPOS_KEY_DOT = 4, YPOS_KEY_SLASH = 4,
275.142 + YPOS_KEY_UP = 4, YPOS_KEY_VOLUMEUP = 4,
275.143 +
275.144 + YPOS_KEY_LEFTSHIFT = 5, YPOS_KEY_LEFTALT = 5, YPOS_KEY_FN = 5, YPOS_KEY_SYM = 5,
275.145 + YPOS_KEY_SPACE = 5, YPOS_KEY_QI = 5, YPOS_KEY_RIGHTCTRL = 5, YPOS_KEY_LEFT = 5,
275.146 + YPOS_KEY_DOWN = 5, YPOS_KEY_RIGHT = 5, YPOS_KEY_VOLUMEDOWN = 5,
275.147 +};
275.148 +
275.149 +/* Keypad matrix mapping. */
275.150 +
275.151 +#define PHYS_KEY(X) {XPOS_KEY_##X, YPOS_KEY_##X, SIZE_KEY_##X}
275.152 +#define PHYS_NULL {0, 0, 0}
275.153 +
275.154 +static const uint32_t keypos[Jz4740_keypad_gpio_inputs_count][Jz4740_keypad_gpio_outputs_count][3] = {
275.155 +
275.156 +{PHYS_KEY(F1), PHYS_KEY(F2), PHYS_KEY(F3), PHYS_KEY(F4), PHYS_KEY(F5), PHYS_KEY(F6),
275.157 + PHYS_KEY(F7), PHYS_NULL},
275.158 +
275.159 +{PHYS_KEY(Q), PHYS_KEY(W), PHYS_KEY(E), PHYS_KEY(R), PHYS_KEY(T), PHYS_KEY(Y),
275.160 + PHYS_KEY(U), PHYS_KEY(I)},
275.161 +
275.162 +{PHYS_KEY(A), PHYS_KEY(S), PHYS_KEY(D), PHYS_KEY(F), PHYS_KEY(G), PHYS_KEY(H),
275.163 + PHYS_KEY(J), PHYS_KEY(K)},
275.164 +
275.165 +{PHYS_KEY(ESCAPE), PHYS_KEY(Z), PHYS_KEY(X), PHYS_KEY(C), PHYS_KEY(V), PHYS_KEY(B),
275.166 + PHYS_KEY(N), PHYS_KEY(M)},
275.167 +
275.168 +{PHYS_KEY(TAB), PHYS_KEY(DOWNSHIFT) /* CAPSLOCK */, PHYS_KEY(BACKSLASH),
275.169 + PHYS_KEY(APOSTROPHE), PHYS_KEY(COMMA), PHYS_KEY(DOT), PHYS_KEY(SLASH), PHYS_KEY(UP)},
275.170 +
275.171 +{PHYS_KEY(O), PHYS_KEY(L), PHYS_KEY(EQUAL), PHYS_KEY(SYM) /* RIGHTALT */,
275.172 + PHYS_KEY(SPACE), PHYS_KEY(QI) /* F13 */, PHYS_KEY(RIGHTCTRL), PHYS_KEY(LEFT)},
275.173 +
275.174 +{PHYS_KEY(F8), PHYS_KEY(P), PHYS_KEY(BACKSPACE), PHYS_KEY(ENTER), PHYS_KEY(VOLUMEUP),
275.175 + PHYS_KEY(VOLUMEDOWN), PHYS_KEY(DOWN), PHYS_KEY(RIGHT)},
275.176 +
275.177 +{PHYS_KEY(LEFTSHIFT), PHYS_KEY(LEFTALT), PHYS_KEY(FN), PHYS_NULL, PHYS_NULL,
275.178 + PHYS_NULL, PHYS_NULL, PHYS_NULL}
275.179 +};
275.180 +
275.181 +
275.182 +
275.183 +static uint32_t bitmask(uint32_t size)
275.184 +{
275.185 + return (1 << size) - 1;
275.186 +}
275.187 +
275.188 +static uint32_t truncate_channel(uint32_t value, uint32_t size)
275.189 +{
275.190 + return (value >> (8 - size)) & bitmask(size);
275.191 +}
275.192 +
275.193 +static void set_pixel(uint32_t pos, uint8_t bpp, uint32_t value)
275.194 +{
275.195 + if (bpp <= 8) *(uint8_t *) pos = value;
275.196 + else if (bpp <= 16) *(uint16_t *) pos = value;
275.197 + else *(uint32_t *) pos = value;
275.198 +}
275.199 +
275.200 +/* Show the state of a key on the display. */
275.201 +
275.202 +static void fill_rectangle(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t rgb)
275.203 +{
275.204 + uint8_t bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
275.205 + uint8_t bytes_per_pixel = fbi.pixel_info.bytes_per_pixel;
275.206 + uint32_t bytes_per_line = fbi.bytes_per_line;
275.207 + uint32_t pos;
275.208 + uint32_t col, row;
275.209 +
275.210 + rgb = (truncate_channel(rgb >> 16, fbi.pixel_info.r.size) << fbi.pixel_info.r.shift) |
275.211 + (truncate_channel(rgb >> 8, fbi.pixel_info.g.size) << fbi.pixel_info.g.shift) |
275.212 + (truncate_channel(rgb, fbi.pixel_info.b.size) << fbi.pixel_info.b.shift);
275.213 +
275.214 + for (row = 0; row < h; row++)
275.215 + {
275.216 + pos = (uint32_t) fb + (y + row) * bytes_per_line + x * bytes_per_pixel;
275.217 +
275.218 + for (col = 0; col < w; col++)
275.219 + {
275.220 + set_pixel(pos, bpp, rgb);
275.221 + pos += bytes_per_pixel;
275.222 + }
275.223 + }
275.224 +}
275.225 +
275.226 +/* Show the keypad status on the display. */
275.227 +
275.228 +static void show_keypad(void)
275.229 +{
275.230 + uint32_t rowsize = fbi.height / ROWS, colsize;
275.231 + uint8_t column, row;
275.232 + uint32_t mask;
275.233 + const uint32_t *pos;
275.234 +
275.235 + for (column = 0; column < columns; column++)
275.236 +
275.237 + for (row = 0, mask = 1 << (rows - 1);
275.238 + row < rows;
275.239 + row++, mask >>= 1)
275.240 + {
275.241 + /* Obtain the physical position. */
275.242 +
275.243 + pos = keypos[row][column];
275.244 +
275.245 + /* Obtain the width of the key. */
275.246 +
275.247 + colsize = (pos[2] * fbi.width) / WIDTH;
275.248 +
275.249 + /* Plot the rectangle for the key. */
275.250 +
275.251 + fill_rectangle((pos[0] * fbi.width) / WIDTH, pos[1] * rowsize, colsize, rowsize,
275.252 + keypad[column] & mask ? 0xffffff : 0);
275.253 + }
275.254 +
275.255 + /* Refresh the display. */
275.256 +
275.257 + l4re_util_video_goos_fb_refresh(&gfb, 0, 0, fbi.width, fbi.height);
275.258 +}
275.259 +
275.260 +
275.261 +
275.262 +int main(void)
275.263 +{
275.264 + l4_cap_idx_t keypad_server;
275.265 + l4re_ds_t mem;
275.266 + l4_msgtag_t tag;
275.267 +
275.268 + if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
275.269 + return 1;
275.270 +
275.271 + if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
275.272 + return 1;
275.273 +
275.274 + if (!(fb = l4re_util_video_goos_fb_attach_buffer(&gfb)))
275.275 + return 1;
275.276 +
275.277 + /* Obtain a reference to the keypad. */
275.278 +
275.279 + keypad_server = l4re_env_get_cap("keypad");
275.280 + if (l4_is_invalid_cap(keypad_server)) return 1;
275.281 +
275.282 + /* Obtain a capability for the keypad data. */
275.283 +
275.284 + mem = l4re_util_cap_alloc();
275.285 + if (l4_is_invalid_cap(mem)) return 1;
275.286 +
275.287 + /* Obtain a reference to the keypad data. */
275.288 +
275.289 + l4_utcb_br()->bdr = 0;
275.290 + l4_utcb_br()->br[0] = L4_RCV_ITEM_SINGLE_CAP | mem;
275.291 +
275.292 + tag = l4_ipc_call(keypad_server, l4_utcb(),
275.293 + l4_msgtag(0, 0, 0, 0), /* label zero, zero words, zero *sent* items */
275.294 + L4_IPC_NEVER);
275.295 +
275.296 + if (l4_ipc_error(tag, l4_utcb())) return 1;
275.297 +
275.298 + /* Attach the keypad data to a region in this task. */
275.299 +
275.300 + if (l4re_rm_attach(&keymem, l4re_ds_size(mem), L4RE_RM_SEARCH_ADDR, mem, 0,
275.301 + L4_PAGESHIFT))
275.302 + return 1;
275.303 +
275.304 + /* Show the keypad state. */
275.305 +
275.306 + keypad = (uint32_t *) keymem;
275.307 +
275.308 + while (1) show_keypad();
275.309 +
275.310 + return 0;
275.311 +}
276.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
276.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/Makefile Sun May 13 01:34:16 2018 +0200
276.3 @@ -0,0 +1,8 @@
276.4 +PKGDIR ?= ../..
276.5 +L4DIR ?= $(PKGDIR)/../..
276.6 +
276.7 +TARGET = ex_qi_lb60_lcd
276.8 +SRC_C = qi_lb60_lcd.c jzlcd.c nanonote_gpm940b0.c memory.c
276.9 +REQUIRES_LIBS = libio l4re_c-util libdrivers-cpm libdrivers-gpio
276.10 +
276.11 +include $(L4DIR)/mk/prog.mk
277.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
277.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/jzlcd.c Sun May 13 01:34:16 2018 +0200
277.3 @@ -0,0 +1,565 @@
277.4 +/*
277.5 + * jz4740 LCD controller configuration.
277.6 + *
277.7 + * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
277.8 + * Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
277.9 + *
277.10 + * This program is free software; you can redistribute it and/or
277.11 + * modify it under the terms of the GNU General Public License as
277.12 + * published by the Free Software Foundation; either version 2 of
277.13 + * the License, or (at your option) any later version.
277.14 + *
277.15 + * This program is distributed in the hope that it will be useful,
277.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
277.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
277.18 + * GNU General Public License for more details.
277.19 + *
277.20 + * You should have received a copy of the GNU General Public License
277.21 + * along with this program; if not, write to the Free Software
277.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
277.23 + * Boston, MA 02110-1301, USA
277.24 + */
277.25 +
277.26 +#include "jzlcd.h"
277.27 +#include "xburst_types.h" /* for REG32 */
277.28 +#include <l4/sys/cache.h> /* for l4_cache functions */
277.29 +
277.30 +/* Useful alignment operations. */
277.31 +
277.32 +static inline void align2(uint32_t *n)
277.33 +{
277.34 + *n = (((*n)+1)>>1)<<1;
277.35 +}
277.36 +
277.37 +static inline void align4(uint32_t *n)
277.38 +{
277.39 + *n = (((*n)+3)>>2)<<2;
277.40 +}
277.41 +
277.42 +static inline void align8(uint32_t *n)
277.43 +{
277.44 + *n = (((*n)+7)>>3)<<3;
277.45 +}
277.46 +
277.47 +
277.48 +
277.49 +/* Register operations. */
277.50 +
277.51 +static inline uint32_t lcd_ctrl_get(vidinfo_t *vid, uint32_t reg)
277.52 +{
277.53 + return REG32(vid->lcd + reg);
277.54 +}
277.55 +
277.56 +static inline void lcd_ctrl_set(vidinfo_t *vid, uint32_t reg, uint32_t value)
277.57 +{
277.58 + REG32(vid->lcd + reg) = value;
277.59 +}
277.60 +
277.61 +
277.62 +
277.63 +/* Configuration operations. */
277.64 +
277.65 +/* Return the number of panels available. */
277.66 +
277.67 +static uint8_t lcd_get_panels(vidinfo_t *vid)
277.68 +{
277.69 + struct jzfb_info *jzfb = vid->jz_fb;
277.70 + uint32_t mode = jzfb->cfg & MODE_MASK;
277.71 +
277.72 + return (mode == MODE_STN_MONO_DUAL) ||
277.73 + (mode == MODE_STN_COLOR_DUAL) ? 2 : 1;
277.74 +}
277.75 +
277.76 +/* Calculate and return the pixel clock frequency. */
277.77 +
277.78 +static uint32_t lcd_get_pixel_clock(vidinfo_t *vid)
277.79 +{
277.80 + struct jzfb_info *jzfb = vid->jz_fb;
277.81 + uint32_t pclk, width_cycles, mode = jzfb->cfg & MODE_MASK;
277.82 +
277.83 + /*
277.84 + Serial mode: 3 pixel clock cycles per pixel (one per channel).
277.85 + Parallel mode: 1 pixel clock cycle per pixel.
277.86 + */
277.87 +
277.88 + if (mode == MODE_8BIT_SERIAL_TFT)
277.89 + width_cycles = jzfb->w * 3;
277.90 + else
277.91 + width_cycles = jzfb->w;
277.92 +
277.93 + /* Derive pixel clock from frame clock. */
277.94 +
277.95 + pclk = jzfb->fclk *
277.96 + (width_cycles + jzfb->hsw + jzfb->elw + jzfb->blw) *
277.97 + (jzfb->h + jzfb->vsw + jzfb->efw + jzfb->bfw);
277.98 +
277.99 + if ((mode == MODE_STN_COLOR_SINGLE) || (mode == MODE_STN_COLOR_DUAL))
277.100 + pclk = (pclk * 3);
277.101 +
277.102 + if ((mode == MODE_STN_COLOR_SINGLE) || (mode == MODE_STN_COLOR_DUAL) ||
277.103 + (mode == MODE_STN_MONO_SINGLE) || (mode == MODE_STN_MONO_DUAL))
277.104 + pclk = pclk >> ((jzfb->cfg & STN_DAT_PINMASK) >> 4);
277.105 +
277.106 + if ((mode == MODE_STN_COLOR_DUAL) || (mode == MODE_STN_MONO_DUAL))
277.107 + pclk >>= 1;
277.108 +
277.109 + return pclk;
277.110 +}
277.111 +
277.112 +
277.113 +
277.114 +/* Functions returning region sizes. */
277.115 +
277.116 +static uint32_t lcd_get_line_size(vidinfo_t *vid)
277.117 +{
277.118 + /* Lines must be aligned to a word boundary. */
277.119 +
277.120 + return ALIGN((vid->jz_fb->w * vid->jz_fb->bpp) / 8, sizeof(uint32_t));
277.121 +}
277.122 +
277.123 +static uint32_t lcd_get_size(vidinfo_t *vid)
277.124 +{
277.125 + return lcd_get_line_size(vid) * vid->jz_fb->h;
277.126 +}
277.127 +
277.128 +static uint32_t lcd_get_aligned_size(vidinfo_t *vid)
277.129 +{
277.130 + /* LCD_CTRL_BST_16 requires 16-word alignment. */
277.131 +
277.132 + return ALIGN(lcd_get_size(vid), 16 * sizeof(uint32_t));
277.133 +}
277.134 +
277.135 +static uint32_t lcd_get_palette_size(vidinfo_t *vid)
277.136 +{
277.137 + /* Get a collection of two-byte entries, one per colour. */
277.138 +
277.139 + if (vid->jz_fb->bpp < 12)
277.140 + return (1 << (vid->jz_fb->bpp)) * sizeof(uint16_t);
277.141 + else
277.142 + return 0;
277.143 +}
277.144 +
277.145 +static uint32_t lcd_get_aligned_palette_size(vidinfo_t *vid)
277.146 +{
277.147 + /* LCD_CTRL_BST_16 requires 16-word alignment. */
277.148 +
277.149 + return ALIGN(lcd_get_palette_size(vid), 16 * sizeof(uint32_t));
277.150 +}
277.151 +
277.152 +static uint32_t lcd_get_descriptors_size(vidinfo_t *vid)
277.153 +{
277.154 + return 3 * sizeof(struct jz_fb_dma_descriptor);
277.155 +}
277.156 +
277.157 +
277.158 +
277.159 +/* Functions returning addresses of each data region.
277.160 +The screen parameter permits the retrieval of virtual or physical addresses. */
277.161 +
277.162 +static uint32_t lcd_get_palette(vidinfo_t *vid, uint32_t screen)
277.163 +{
277.164 + /* Use memory at the end of the allocated region for the palette. */
277.165 +
277.166 + return screen + jz4740_lcd_get_screen_size(vid) - lcd_get_aligned_palette_size(vid);
277.167 +}
277.168 +
277.169 +static uint32_t lcd_get_framebuffer(uint8_t panel, vidinfo_t *vid, uint32_t screen)
277.170 +{
277.171 + /* Framebuffers for panels are allocated at the start of the region. */
277.172 +
277.173 + return screen + (panel * lcd_get_aligned_size(vid));
277.174 +}
277.175 +
277.176 +
277.177 +
277.178 +/* Initialisation functions. */
277.179 +
277.180 +static uint32_t jz_lcd_stn_init(uint32_t stnH, vidinfo_t *vid)
277.181 +{
277.182 + struct jzfb_info *jzfb = vid->jz_fb;
277.183 + uint32_t val = 0;
277.184 +
277.185 + switch (jzfb->bpp) {
277.186 + case 1:
277.187 + /* val |= LCD_CTRL_PEDN; */
277.188 + case 2:
277.189 + val |= LCD_CTRL_FRC_2;
277.190 + break;
277.191 +
277.192 + case 4:
277.193 + val |= LCD_CTRL_FRC_4;
277.194 + break;
277.195 +
277.196 + case 8:
277.197 + default:
277.198 + val |= LCD_CTRL_FRC_16;
277.199 + break;
277.200 + }
277.201 +
277.202 + switch (jzfb->cfg & STN_DAT_PINMASK) {
277.203 + case STN_DAT_PIN1:
277.204 + /* Do not adjust the hori-param value. */
277.205 + break;
277.206 +
277.207 + case STN_DAT_PIN2:
277.208 + align2(&jzfb->hsw);
277.209 + align2(&jzfb->elw);
277.210 + align2(&jzfb->blw);
277.211 + break;
277.212 +
277.213 + case STN_DAT_PIN4:
277.214 + align4(&jzfb->hsw);
277.215 + align4(&jzfb->elw);
277.216 + align4(&jzfb->blw);
277.217 + break;
277.218 +
277.219 + case STN_DAT_PIN8:
277.220 + align8(&jzfb->hsw);
277.221 + align8(&jzfb->elw);
277.222 + align8(&jzfb->blw);
277.223 + break;
277.224 + }
277.225 +
277.226 + lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw);
277.227 + lcd_ctrl_set(vid, LCD_HSYNC, ((jzfb->blw + jzfb->w) << 16) | (jzfb->blw + jzfb->w + jzfb->hsw));
277.228 +
277.229 + /* Screen setting */
277.230 + lcd_ctrl_set(vid, LCD_VAT, ((jzfb->blw + jzfb->w + jzfb->hsw + jzfb->elw) << 16) | (stnH + jzfb->vsw + jzfb->bfw + jzfb->efw));
277.231 + lcd_ctrl_set(vid, LCD_DAH, (jzfb->blw << 16) | (jzfb->blw + jzfb->w));
277.232 + lcd_ctrl_set(vid, LCD_DAV, stnH);
277.233 +
277.234 + /* AC BIAs signal */
277.235 + lcd_ctrl_set(vid, LCD_PS, stnH+jzfb->vsw+jzfb->efw+jzfb->bfw);
277.236 +
277.237 + return val;
277.238 +}
277.239 +
277.240 +static void jz_lcd_tft_init(vidinfo_t *vid)
277.241 +{
277.242 + struct jzfb_info *jzfb = vid->jz_fb;
277.243 +
277.244 + lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw);
277.245 + lcd_ctrl_set(vid, LCD_HSYNC, jzfb->hsw);
277.246 + lcd_ctrl_set(vid, LCD_DAV, ((jzfb->vsw + jzfb->bfw) << 16) | (jzfb->vsw + jzfb->bfw + jzfb->h));
277.247 + lcd_ctrl_set(vid, LCD_DAH, ((jzfb->hsw + jzfb->blw) << 16) | (jzfb->hsw + jzfb->blw + jzfb->w));
277.248 + lcd_ctrl_set(vid, LCD_VAT, (((jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw)) << 16) |
277.249 + (jzfb->vsw + jzfb->bfw + jzfb->h + jzfb->efw));
277.250 +}
277.251 +
277.252 +static void jz_lcd_samsung_init(vidinfo_t *vid)
277.253 +{
277.254 + struct jzfb_info *jzfb = vid->jz_fb;
277.255 + uint32_t pclk = lcd_get_pixel_clock(vid);
277.256 + uint32_t total, tp_s, tp_e, ckv_s, ckv_e;
277.257 + uint32_t rev_s, rev_e, inv_s, inv_e;
277.258 +
277.259 + jz_lcd_tft_init(vid);
277.260 +
277.261 + total = jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw;
277.262 + tp_s = jzfb->blw + jzfb->w + 1;
277.263 + tp_e = tp_s + 1;
277.264 + /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */
277.265 + ckv_s = tp_s - pclk/(1000000000/4100);
277.266 + ckv_e = tp_s + total;
277.267 + rev_s = tp_s - 11; /* -11.5 clk */
277.268 + rev_e = rev_s + total;
277.269 + inv_s = tp_s;
277.270 + inv_e = inv_s + total;
277.271 + lcd_ctrl_set(vid, LCD_CLS, (tp_s << 16) | tp_e);
277.272 + lcd_ctrl_set(vid, LCD_PS, (ckv_s << 16) | ckv_e);
277.273 + lcd_ctrl_set(vid, LCD_SPL, (rev_s << 16) | rev_e);
277.274 + lcd_ctrl_set(vid, LCD_REV, (inv_s << 16) | inv_e);
277.275 + jzfb->cfg |= STFT_REVHI | STFT_SPLHI;
277.276 +}
277.277 +
277.278 +static void jz_lcd_sharp_init(vidinfo_t *vid)
277.279 +{
277.280 + struct jzfb_info *jzfb = vid->jz_fb;
277.281 + uint32_t total, cls_s, cls_e, ps_s, ps_e;
277.282 + uint32_t spl_s, spl_e, rev_s, rev_e;
277.283 +
277.284 + jz_lcd_tft_init(vid);
277.285 +
277.286 + total = jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw;
277.287 + spl_s = 1;
277.288 + spl_e = spl_s + 1;
277.289 + cls_s = 0;
277.290 + cls_e = total - 60; /* > 4us (pclk = 80ns) */
277.291 + ps_s = cls_s;
277.292 + ps_e = cls_e;
277.293 + rev_s = total - 40; /* > 3us (pclk = 80ns) */
277.294 + rev_e = rev_s + total;
277.295 + jzfb->cfg |= STFT_PSHI;
277.296 + lcd_ctrl_set(vid, LCD_SPL, (spl_s << 16) | spl_e);
277.297 + lcd_ctrl_set(vid, LCD_CLS, (cls_s << 16) | cls_e);
277.298 + lcd_ctrl_set(vid, LCD_PS, (ps_s << 16) | ps_e);
277.299 + lcd_ctrl_set(vid, LCD_REV, (rev_s << 16) | rev_e);
277.300 +}
277.301 +
277.302 +
277.303 +
277.304 +/* Palette initialisation. */
277.305 +
277.306 +static inline uint16_t rgb8_to_rgb16(uint8_t rgb)
277.307 +{
277.308 + return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10);
277.309 +}
277.310 +
277.311 +static inline uint16_t rgb4_to_rgb16(uint8_t rgb)
277.312 +{
277.313 + return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f);
277.314 +}
277.315 +
277.316 +static void lcd_init_palette(vidinfo_t *vid, uint32_t palette)
277.317 +{
277.318 + uint16_t *entry = (uint16_t *) palette;
277.319 + uint16_t *end = entry + (1 << (vid->jz_fb->bpp));
277.320 + uint8_t value = 0;
277.321 +
277.322 + while (entry < end)
277.323 + {
277.324 + switch (vid->jz_fb->bpp)
277.325 + {
277.326 + case 4:
277.327 + *entry = rgb4_to_rgb16(value);
277.328 + break;
277.329 +
277.330 + case 8:
277.331 + default:
277.332 + *entry = rgb8_to_rgb16(value);
277.333 + break;
277.334 + }
277.335 +
277.336 + value++;
277.337 + entry++;
277.338 + }
277.339 +}
277.340 +
277.341 +
277.342 +
277.343 +/* Public functions. */
277.344 +
277.345 +uint32_t jz4740_lcd_get_aligned_size(vidinfo_t *vid)
277.346 +{
277.347 + return lcd_get_aligned_size(vid);
277.348 +}
277.349 +
277.350 +uint32_t jz4740_lcd_get_descriptors_size(vidinfo_t *vid)
277.351 +{
277.352 + return lcd_get_descriptors_size(vid);
277.353 +}
277.354 +
277.355 +uint32_t jz4740_lcd_get_line_size(vidinfo_t *vid)
277.356 +{
277.357 + return lcd_get_line_size(vid);
277.358 +}
277.359 +
277.360 +/* Return the total size of the required memory. */
277.361 +
277.362 +uint32_t jz4740_lcd_get_screen_size(vidinfo_t *vid)
277.363 +{
277.364 + return lcd_get_aligned_size(vid) * lcd_get_panels(vid) +
277.365 + lcd_get_aligned_palette_size(vid);
277.366 +}
277.367 +
277.368 +/* Return the calculated pixel clock frequency for the display. */
277.369 +
277.370 +uint32_t jz4740_lcd_get_pixel_clock(vidinfo_t *vid)
277.371 +{
277.372 + return lcd_get_pixel_clock(vid);
277.373 +}
277.374 +
277.375 +/* Set the LCD controller address. */
277.376 +
277.377 +void jz4740_lcd_set_base(vidinfo_t *vid, void *lcd_base)
277.378 +{
277.379 + vid->lcd = lcd_base;
277.380 +}
277.381 +
277.382 +/* Initialise the LCD controller with the memory, panel and framebuffer details. */
277.383 +
277.384 +void jz4740_lcd_ctrl_init(
277.385 + struct jz_fb_dma_descriptor *desc_vaddr,
277.386 + struct jz_fb_dma_descriptor *desc_paddr,
277.387 + void *fb_vaddr, void *fb_paddr,
277.388 + vidinfo_t *vid)
277.389 +{
277.390 + struct jz_fb_dma_descriptor *first, *second = 0;
277.391 +
277.392 + /* Initialise a palette for lower colour depths. */
277.393 +
277.394 + if (vid->jz_fb->bpp < 12)
277.395 + lcd_init_palette(vid, lcd_get_palette(vid, (uint32_t) fb_vaddr));
277.396 +
277.397 + /* Populate descriptors. */
277.398 +
277.399 + /* Provide the first framebuffer descriptor in single and dual modes. */
277.400 +
277.401 + desc_vaddr[0].fsadr = lcd_get_framebuffer(0, vid, (uint32_t) fb_paddr);
277.402 + desc_vaddr[0].fidr = 0;
277.403 + desc_vaddr[0].ldcmd = lcd_get_size(vid) / 4; /* length in words */
277.404 +
277.405 + /* Provide the second framebuffer descriptor only in dual-panel mode. */
277.406 +
277.407 + if (lcd_get_panels(vid) == 2)
277.408 + {
277.409 + desc_vaddr[1].fdadr = desc_paddr + 1;
277.410 + desc_vaddr[1].fsadr = lcd_get_framebuffer(1, vid, (uint32_t) fb_paddr);
277.411 + desc_vaddr[1].fidr = 0;
277.412 + desc_vaddr[1].ldcmd = lcd_get_size(vid) / 4;
277.413 +
277.414 + /* Note the address to be provided for the second channel. */
277.415 +
277.416 + second = desc_paddr + 1;
277.417 + }
277.418 +
277.419 + /* Initialise palette descriptor details if a palette is to be used. */
277.420 +
277.421 + /* Assume any mode with <12 bpp is palette driven. */
277.422 +
277.423 + if (vid->jz_fb->bpp < 12)
277.424 + {
277.425 + desc_vaddr[2].fsadr = lcd_get_palette(vid, (uint32_t) fb_paddr);
277.426 + desc_vaddr[2].fidr = 0;
277.427 + desc_vaddr[2].ldcmd = (lcd_get_palette_size(vid) / 4) | LCD_CMD_PAL;
277.428 +
277.429 + /* Flip back and forth between the palette and framebuffer. */
277.430 +
277.431 + desc_vaddr[2].fdadr = desc_paddr;
277.432 + desc_vaddr[0].fdadr = desc_paddr + 2;
277.433 +
277.434 + /* Provide the palette descriptor address first. */
277.435 +
277.436 + first = desc_paddr + 2;
277.437 + }
277.438 + else
277.439 + {
277.440 + /* No palette: always use the framebuffer descriptor. */
277.441 +
277.442 + desc_vaddr[0].fdadr = desc_paddr;
277.443 + first = desc_paddr;
277.444 + }
277.445 +
277.446 + /* Flush cached structure data. */
277.447 +
277.448 + l4_cache_clean_data((unsigned long) desc_vaddr,
277.449 + (unsigned long) desc_vaddr + lcd_get_descriptors_size(vid));
277.450 +
277.451 + /* Configure DMA by setting frame descriptor addresses. */
277.452 +
277.453 + lcd_ctrl_set(vid, LCD_DA0, (uint32_t) first);
277.454 +
277.455 + if (lcd_get_panels(vid) == 2)
277.456 + lcd_ctrl_set(vid, LCD_DA1, (uint32_t) second);
277.457 +}
277.458 +
277.459 +/* Initialise the LCD registers. */
277.460 +
277.461 +void jz4740_lcd_hw_init(vidinfo_t *vid)
277.462 +{
277.463 + struct jzfb_info *jzfb = vid->jz_fb;
277.464 + uint32_t mode = vid->jz_fb->cfg & MODE_MASK;
277.465 + uint32_t val = 0;
277.466 +
277.467 + /* Compute control register flags. */
277.468 +
277.469 + switch (jzfb->bpp) {
277.470 + case 1:
277.471 + val |= LCD_CTRL_BPP_1;
277.472 + break;
277.473 +
277.474 + case 2:
277.475 + val |= LCD_CTRL_BPP_2;
277.476 + break;
277.477 +
277.478 + case 4:
277.479 + val |= LCD_CTRL_BPP_4;
277.480 + break;
277.481 +
277.482 + case 8:
277.483 + val |= LCD_CTRL_BPP_8;
277.484 + break;
277.485 +
277.486 + case 15:
277.487 + val |= LCD_CTRL_RGB555;
277.488 + case 16:
277.489 + val |= LCD_CTRL_BPP_16;
277.490 + break;
277.491 +
277.492 + case 17 ... 32:
277.493 + val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */
277.494 + break;
277.495 +
277.496 + default:
277.497 + val |= LCD_CTRL_BPP_16; /* default to 16bpp */
277.498 + break;
277.499 + }
277.500 +
277.501 + /* Set various configuration registers for the panel. */
277.502 +
277.503 + switch (mode) {
277.504 + case MODE_STN_MONO_DUAL:
277.505 + case MODE_STN_COLOR_DUAL:
277.506 + val |= jz_lcd_stn_init(jzfb->h >> 1, vid);
277.507 + break;
277.508 +
277.509 + case MODE_STN_MONO_SINGLE:
277.510 + case MODE_STN_COLOR_SINGLE:
277.511 + val |= jz_lcd_stn_init(jzfb->h, vid);
277.512 + break;
277.513 +
277.514 + case MODE_TFT_GEN:
277.515 + case MODE_TFT_CASIO:
277.516 + case MODE_8BIT_SERIAL_TFT:
277.517 + case MODE_TFT_18BIT:
277.518 + jz_lcd_tft_init(vid);
277.519 + break;
277.520 +
277.521 + case MODE_TFT_SAMSUNG:
277.522 + jz_lcd_samsung_init(vid);
277.523 + break;
277.524 +
277.525 + case MODE_TFT_SHARP:
277.526 + jz_lcd_sharp_init(vid);
277.527 + break;
277.528 +
277.529 + default:
277.530 + break;
277.531 + }
277.532 +
277.533 + /* Further control register and panel configuration. */
277.534 +
277.535 + val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */
277.536 + val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */
277.537 +
277.538 + lcd_ctrl_set(vid, LCD_CTRL, val);
277.539 + lcd_ctrl_set(vid, LCD_CFG, jzfb->cfg);
277.540 +}
277.541 +
277.542 +/* Set the colour depth. */
277.543 +
277.544 +void jz4740_lcd_set_bpp(uint8_t bpp, vidinfo_t *vid)
277.545 +{
277.546 + vid->jz_fb->bpp = bpp;
277.547 +}
277.548 +
277.549 +void jz4740_lcd_enable(vidinfo_t *vid)
277.550 +{
277.551 + /* Clear the disable bit (DIS) and set the enable bit (ENA). */
277.552 +
277.553 + lcd_ctrl_set(vid, LCD_CTRL, (lcd_ctrl_get(vid, LCD_CTRL) & ~LCD_CTRL_DIS) | LCD_CTRL_ENA);
277.554 +}
277.555 +
277.556 +void jz4740_lcd_disable(vidinfo_t *vid)
277.557 +{
277.558 + /* Set the disable bit (DIS). */
277.559 +
277.560 + lcd_ctrl_set(vid, LCD_CTRL, lcd_ctrl_get(vid, LCD_CTRL) | LCD_CTRL_DIS);
277.561 +}
277.562 +
277.563 +void jz4740_lcd_quick_disable(vidinfo_t *vid)
277.564 +{
277.565 + /* Clear the enable bit (ENA) for quick disable. */
277.566 +
277.567 + lcd_ctrl_set(vid, LCD_CTRL, lcd_ctrl_get(vid, LCD_CTRL) & ~LCD_CTRL_ENA);
277.568 +}
278.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
278.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/jzlcd.h Sun May 13 01:34:16 2018 +0200
278.3 @@ -0,0 +1,236 @@
278.4 +/*
278.5 + * U-Boot and jz4740 LCD controller definitions.
278.6 + *
278.7 + * Copyright (C) 2001 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
278.8 + * Copyright (C) 2005-2007, Ingenic Semiconductor Inc.
278.9 + * Copyright (C) 2009 Qi Hardware Inc.
278.10 + * Author: Xiangfu Liu <xiangfu@sharism.cc>
278.11 + * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
278.12 + * Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
278.13 + *
278.14 + * This program is free software; you can redistribute it and/or
278.15 + * modify it under the terms of the GNU General Public License as
278.16 + * published by the Free Software Foundation; either version 2 of
278.17 + * the License, or (at your option) any later version.
278.18 + *
278.19 + * This program is distributed in the hope that it will be useful,
278.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
278.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
278.22 + * GNU General Public License for more details.
278.23 + *
278.24 + * You should have received a copy of the GNU General Public License
278.25 + * along with this program; if not, write to the Free Software
278.26 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
278.27 + * Boston, MA 02110-1301, USA
278.28 + */
278.29 +
278.30 +#ifndef __JZLCD_H__
278.31 +#define __JZLCD_H__
278.32 +
278.33 +#include <stdint.h>
278.34 +
278.35 +/* Framebuffer characteristics. */
278.36 +
278.37 +struct jzfb_info {
278.38 + uint32_t cfg; /* panel mode and pin usage etc. */
278.39 + uint32_t w; /* display width in pixels */
278.40 + uint32_t h; /* display height in pixels */
278.41 + uint32_t bpp; /* bits per pixel */
278.42 + uint32_t fclk; /* frame clock */
278.43 + uint32_t hsw; /* hsync width, in pixel clock */
278.44 + uint32_t vsw; /* vsync width, in line count */
278.45 + uint32_t elw; /* end of line, in pixel clock */
278.46 + uint32_t blw; /* begin of line, in pixel clock */
278.47 + uint32_t efw; /* end of frame, in line count */
278.48 + uint32_t bfw; /* begin of frame, in line count */
278.49 +};
278.50 +
278.51 +/* LCD controller stucture for jz4740. */
278.52 +
278.53 +struct jz_fb_dma_descriptor {
278.54 + struct jz_fb_dma_descriptor *fdadr; /* frame descriptor address register */
278.55 + uint32_t fsadr; /* frame source address register */
278.56 + uint32_t fidr; /* frame identifier register */
278.57 + uint32_t ldcmd; /* command register */
278.58 +};
278.59 +
278.60 +/* Display characteristics and memory resources. */
278.61 +
278.62 +typedef struct vidinfo {
278.63 + struct jzfb_info *jz_fb; /* framebuffer and panel properties */
278.64 + void *lcd; /* address of LCD controller registers */
278.65 +} vidinfo_t;
278.66 +
278.67 +
278.68 +
278.69 +/* Public functions. */
278.70 +
278.71 +uint32_t jz4740_lcd_get_aligned_size(vidinfo_t *vid);
278.72 +uint32_t jz4740_lcd_get_descriptors_size(vidinfo_t *vid);
278.73 +uint32_t jz4740_lcd_get_line_size(vidinfo_t *vid);
278.74 +uint32_t jz4740_lcd_get_screen_size(vidinfo_t *vid);
278.75 +uint32_t jz4740_lcd_get_pixel_clock(vidinfo_t *vid);
278.76 +
278.77 +void jz4740_lcd_set_base(vidinfo_t *vid, void *lcd_base);
278.78 +
278.79 +void jz4740_lcd_ctrl_init(
278.80 + struct jz_fb_dma_descriptor *desc_vaddr,
278.81 + struct jz_fb_dma_descriptor *desc_paddr,
278.82 + void *fb_vaddr, void *fb_paddr,
278.83 + vidinfo_t *vid);
278.84 +
278.85 +void jz4740_lcd_hw_init(vidinfo_t *vid);
278.86 +void jz4740_lcd_set_bpp(uint8_t bpp, vidinfo_t *vid);
278.87 +void jz4740_lcd_enable(vidinfo_t *vid);
278.88 +void jz4740_lcd_disable(vidinfo_t *vid);
278.89 +void jz4740_lcd_quick_disable(vidinfo_t *vid);
278.90 +
278.91 +
278.92 +
278.93 +/* Alignment/rounding macros. */
278.94 +
278.95 +#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1)
278.96 +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
278.97 +
278.98 +/* Display device mode select (LCD_CFG.MODE). */
278.99 +
278.100 +#define MODE_MASK 0x0f
278.101 +#define MODE_TFT_GEN 0x00
278.102 +#define MODE_TFT_SHARP 0x01
278.103 +#define MODE_TFT_CASIO 0x02
278.104 +#define MODE_TFT_SAMSUNG 0x03
278.105 +#define MODE_CCIR656_NONINT 0x04
278.106 +#define MODE_CCIR656_INT 0x05
278.107 +#define MODE_STN_COLOR_SINGLE 0x08
278.108 +#define MODE_STN_MONO_SINGLE 0x09
278.109 +#define MODE_STN_COLOR_DUAL 0x0a
278.110 +#define MODE_STN_MONO_DUAL 0x0b
278.111 +#define MODE_8BIT_SERIAL_TFT 0x0c
278.112 +
278.113 +/* 16-bit or 18-bit TFT panel selection (LCD_CFG.18/16). */
278.114 +
278.115 +#define MODE_TFT_18BIT (1<<7)
278.116 +
278.117 +/* STN pin utilisation (LCD_CFG.PDW). */
278.118 +
278.119 +#define STN_DAT_PIN1 (0x00 << 4)
278.120 +#define STN_DAT_PIN2 (0x01 << 4)
278.121 +#define STN_DAT_PIN4 (0x02 << 4)
278.122 +#define STN_DAT_PIN8 (0x03 << 4)
278.123 +#define STN_DAT_PINMASK STN_DAT_PIN8
278.124 +
278.125 +/* Pin reset states (LCD_CFG). */
278.126 +
278.127 +#define STFT_PSHI (1 << 15)
278.128 +#define STFT_CLSHI (1 << 14)
278.129 +#define STFT_SPLHI (1 << 13)
278.130 +#define STFT_REVHI (1 << 12)
278.131 +
278.132 +/* Sync direction (LCD_CFG.SYNDIR). */
278.133 +
278.134 +#define SYNC_MASTER (0 << 16)
278.135 +#define SYNC_SLAVE (1 << 16)
278.136 +
278.137 +/* Data enable polarity (LCD_CFG.DEP). */
278.138 +
278.139 +#define DE_P (0 << 9)
278.140 +#define DE_N (1 << 9)
278.141 +
278.142 +/* Pixel clock polarity (LCD_CFG.PCP). */
278.143 +
278.144 +#define PCLK_P (0 << 10)
278.145 +#define PCLK_N (1 << 10)
278.146 +
278.147 +/* Horizontal sync polarity (LCD_CFG.HSP). */
278.148 +
278.149 +#define HSYNC_P (0 << 11)
278.150 +#define HSYNC_N (1 << 11)
278.151 +
278.152 +/* Vertical sync polarity (LCD_CFG.VSP). */
278.153 +
278.154 +#define VSYNC_P (0 << 8)
278.155 +#define VSYNC_N (1 << 8)
278.156 +
278.157 +/* Inverse output data (LCD_CFG.INVDAT). */
278.158 +
278.159 +#define DATA_NORMAL (0 << 17)
278.160 +#define DATA_INVERSE (1 << 17)
278.161 +
278.162 +/* Register offsets. */
278.163 +
278.164 +#define LCD_CFG 0x00 /* LCD Configure Register */
278.165 +#define LCD_VSYNC 0x04 /* Vertical Synchronize Register */
278.166 +#define LCD_HSYNC 0x08 /* Horizontal Synchronize Register */
278.167 +#define LCD_VAT 0x0c /* Virtual Area Setting Register */
278.168 +#define LCD_DAH 0x10 /* Display Area Horizontal Start/End Point */
278.169 +#define LCD_DAV 0x14 /* Display Area Vertical Start/End Point */
278.170 +#define LCD_PS 0x18 /* PS Signal Setting */
278.171 +#define LCD_CLS 0x1c /* CLS Signal Setting */
278.172 +#define LCD_SPL 0x20 /* SPL Signal Setting */
278.173 +#define LCD_REV 0x24 /* REV Signal Setting */
278.174 +#define LCD_CTRL 0x30 /* LCD Control Register */
278.175 +#define LCD_STATE 0x34 /* LCD Status Register */
278.176 +#define LCD_IID 0x38 /* Interrupt ID Register */
278.177 +#define LCD_DA0 0x40 /* Descriptor Address Register 0 */
278.178 +#define LCD_SA0 0x44 /* Source Address Register 0 */
278.179 +#define LCD_FID0 0x48 /* Frame ID Register 0 */
278.180 +#define LCD_CMD0 0x4c /* DMA Command Register 0 */
278.181 +#define LCD_DA1 0x50 /* Descriptor Address Register 1 */
278.182 +#define LCD_SA1 0x54 /* Source Address Register 1 */
278.183 +#define LCD_FID1 0x58 /* Frame ID Register 1 */
278.184 +#define LCD_CMD1 0x5c /* DMA Command Register 1 */
278.185 +
278.186 +/* Burst length selection (LCD_CTRL.BST). */
278.187 +
278.188 +#define LCD_CTRL_BST_MASK (0x03 << 28)
278.189 +#define LCD_CTRL_BST_4 (0 << 28) /* 4-word */
278.190 +#define LCD_CTRL_BST_8 (1 << 28) /* 8-word */
278.191 +#define LCD_CTRL_BST_16 (2 << 28) /* 16-word */
278.192 +
278.193 +/* RGB mode (LCD_CTRL.RGB). */
278.194 +
278.195 +#define LCD_CTRL_RGB565 (0 << 27) /* RGB565 mode */
278.196 +#define LCD_CTRL_RGB555 (1 << 27) /* RGB555 mode */
278.197 +
278.198 +/* Output FIFO underrun protection (LCD_CTRL.OFUP). */
278.199 +
278.200 +#define LCD_CTRL_OFUP (1 << 26) /* Output FIFO underrun protection enable */
278.201 +
278.202 +/* STN FRC algorithm selection (LCD_CTRL.FRC). */
278.203 +
278.204 +#define LCD_CTRL_FRC_16 (0 << 24) /* 16 grayscale */
278.205 +#define LCD_CTRL_FRC_4 (1 << 24) /* 4 grayscale */
278.206 +#define LCD_CTRL_FRC_2 (2 << 24) /* 2 grayscale */
278.207 +#define LCD_CTRL_FRC_MASK (0x03 << 24)
278.208 +
278.209 +/* Load palette delay counter (LCD_CTRL.PDD) */
278.210 +
278.211 +#define LCD_CTRL_PDD_MASK (0xff << 16)
278.212 +
278.213 +#define LCD_CTRL_EOFM (1 << 13) /* EOF interrupt mask */
278.214 +#define LCD_CTRL_SOFM (1 << 12) /* SOF interrupt mask */
278.215 +#define LCD_CTRL_OFUM (1 << 11) /* Output FIFO underrun interrupt mask */
278.216 +#define LCD_CTRL_IFUM0 (1 << 10) /* Input FIFO 0 underrun interrupt mask */
278.217 +#define LCD_CTRL_IFUM1 (1 << 9) /* Input FIFO 1 underrun interrupt mask */
278.218 +#define LCD_CTRL_LDDM (1 << 8) /* LCD disable done interrupt mask */
278.219 +#define LCD_CTRL_QDM (1 << 7) /* LCD quick disable done interrupt mask */
278.220 +#define LCD_CTRL_BEDN (1 << 6) /* Endian selection */
278.221 +#define LCD_CTRL_PEDN (1 << 5) /* Endian in byte:0-msb first, 1-lsb first */
278.222 +#define LCD_CTRL_DIS (1 << 4) /* Disable indicate bit */
278.223 +#define LCD_CTRL_ENA (1 << 3) /* LCD enable bit */
278.224 +
278.225 +/* Bits per pixel (LCD_CTRL.BPP). */
278.226 +
278.227 +#define LCD_CTRL_BPP_1 0 /* 1 bpp */
278.228 +#define LCD_CTRL_BPP_2 1 /* 2 bpp */
278.229 +#define LCD_CTRL_BPP_4 2 /* 4 bpp */
278.230 +#define LCD_CTRL_BPP_8 3 /* 8 bpp */
278.231 +#define LCD_CTRL_BPP_16 4 /* 15/16 bpp */
278.232 +#define LCD_CTRL_BPP_18_24 5 /* 18/24/32 bpp */
278.233 +#define LCD_CTRL_BPP_MASK 0x07
278.234 +
278.235 +/* Palette buffer (LCD_CMDx.PAL). */
278.236 +
278.237 +#define LCD_CMD_PAL (1 << 28)
278.238 +
278.239 +#endif /* __JZLCD_H__ */
279.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
279.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/memory.c Sun May 13 01:34:16 2018 +0200
279.3 @@ -0,0 +1,78 @@
279.4 +/*
279.5 + * Memory allocation utility functions.
279.6 + *
279.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
279.8 + *
279.9 + * This program is free software; you can redistribute it and/or
279.10 + * modify it under the terms of the GNU General Public License as
279.11 + * published by the Free Software Foundation; either version 2 of
279.12 + * the License, or (at your option) any later version.
279.13 + *
279.14 + * This program is distributed in the hope that it will be useful,
279.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
279.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
279.17 + * GNU General Public License for more details.
279.18 + *
279.19 + * You should have received a copy of the GNU General Public License
279.20 + * along with this program; if not, write to the Free Software
279.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
279.22 + * Boston, MA 02110-1301, USA
279.23 + */
279.24 +
279.25 +#include <l4/io/io.h>
279.26 +#include <l4/re/env.h>
279.27 +#include <l4/re/c/mem_alloc.h>
279.28 +#include <l4/re/c/util/cap_alloc.h>
279.29 +#include <l4/util/util.h>
279.30 +#include <l4/vbus/vbus.h>
279.31 +
279.32 +#include "memory.h"
279.33 +
279.34 +int get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)
279.35 +{
279.36 + return l4io_lookup_device(hid, dh, 0, rh);
279.37 +}
279.38 +
279.39 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
279.40 + enum l4io_resource_types_t type)
279.41 +{
279.42 + int current = 0, result = 0;
279.43 + l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
279.44 +
279.45 + do
279.46 + {
279.47 + result = l4vbus_get_resource(vbus, dh, current, res);
279.48 + current++;
279.49 + }
279.50 + while ((!result) && (res->type != type));
279.51 +
279.52 + return result;
279.53 +}
279.54 +
279.55 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)
279.56 +{
279.57 + l4io_device_handle_t dh;
279.58 + l4io_resource_handle_t rh;
279.59 + l4io_resource_t res;
279.60 + int result;
279.61 +
279.62 + result = get_device(hid, &dh, &rh);
279.63 +
279.64 + if (result < 0)
279.65 + return result;
279.66 +
279.67 + result = get_resource(dh, &res, L4IO_RESOURCE_MEM);
279.68 +
279.69 + if (result)
279.70 + return result;
279.71 +
279.72 + result = l4io_request_iomem(res.start, res.end - res.start + 1,
279.73 + L4IO_MEM_NONCACHED, start);
279.74 +
279.75 + if (result)
279.76 + return result;
279.77 +
279.78 + *end = *start + (res.end - res.start + 1);
279.79 +
279.80 + return 0;
279.81 +}
280.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
280.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/memory.h Sun May 13 01:34:16 2018 +0200
280.3 @@ -0,0 +1,36 @@
280.4 +/*
280.5 + * Memory allocation utility functions.
280.6 + *
280.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
280.8 + *
280.9 + * This program is free software; you can redistribute it and/or
280.10 + * modify it under the terms of the GNU General Public License as
280.11 + * published by the Free Software Foundation; either version 2 of
280.12 + * the License, or (at your option) any later version.
280.13 + *
280.14 + * This program is distributed in the hope that it will be useful,
280.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
280.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
280.17 + * GNU General Public License for more details.
280.18 + *
280.19 + * You should have received a copy of the GNU General Public License
280.20 + * along with this program; if not, write to the Free Software
280.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
280.22 + * Boston, MA 02110-1301, USA
280.23 + */
280.24 +
280.25 +#ifndef __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__
280.26 +#define __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__
280.27 +
280.28 +#include <l4/io/io.h>
280.29 +#include <l4/sys/types.h>
280.30 +
280.31 +int get_device(char const *hid, l4io_device_handle_t *dh,
280.32 + l4io_resource_handle_t *rh);
280.33 +
280.34 +int get_resource(l4io_device_handle_t dh, l4io_resource_t *res,
280.35 + enum l4io_resource_types_t type);
280.36 +
280.37 +int get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end);
280.38 +
280.39 +#endif /* __DRIVERS_LCD_ARCH_JZ4740_MEMORY_H__ */
281.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
281.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/nanonote_gpm940b0.c Sun May 13 01:34:16 2018 +0200
281.3 @@ -0,0 +1,37 @@
281.4 +/*
281.5 + * Ben NanoNote screen details.
281.6 + *
281.7 + * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
281.8 + * Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
281.9 + *
281.10 + * This program is free software; you can redistribute it and/or
281.11 + * modify it under the terms of the GNU General Public License as
281.12 + * published by the Free Software Foundation; either version 2 of
281.13 + * the License, or (at your option) any later version.
281.14 + *
281.15 + * This program is distributed in the hope that it will be useful,
281.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
281.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
281.18 + * GNU General Public License for more details.
281.19 + *
281.20 + * You should have received a copy of the GNU General Public License
281.21 + * along with this program; if not, write to the Free Software
281.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
281.23 + * Boston, MA 02110-1301, USA
281.24 + */
281.25 +
281.26 +#include "jzlcd.h"
281.27 +
281.28 +struct jzfb_info nanonote_fb_info = {
281.29 + .cfg=MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N | DE_P,
281.30 + .w=320, .h=240, /* dimensions */
281.31 + .bpp=32, /* bits per pixel */
281.32 + .fclk=70, /* frame clock rate */
281.33 + .hsw=1, .vsw=1, /* sync widths */
281.34 + .elw=273, .blw=140, /* line limits: end/front, beginning/back porch */
281.35 + .efw=1, .bfw=20, /* frame limits: end/front, beginning/back porch */
281.36 +};
281.37 +
281.38 +vidinfo_t nanonote_panel_info = {
281.39 + .jz_fb=&nanonote_fb_info /* wrap the above */
281.40 +};
282.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
282.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/nanonote_gpm940b0.h Sun May 13 01:34:16 2018 +0200
282.3 @@ -0,0 +1,8 @@
282.4 +#ifndef __NANONOTE_GPM940B0_H__
282.5 +#define __NANONOTE_GPM940B0_H__
282.6 +
282.7 +#include "jzlcd.h"
282.8 +
282.9 +extern vidinfo_t nanonote_panel_info;
282.10 +
282.11 +#endif /* __NANONOTE_GPM940B0_H__ */
283.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
283.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/qi_lb60_lcd.c Sun May 13 01:34:16 2018 +0200
283.3 @@ -0,0 +1,297 @@
283.4 +/*
283.5 + * Access the LCD and related GPIOs on the Ben NanoNote.
283.6 + *
283.7 + * (c) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
283.8 + *
283.9 + * This program is free software; you can redistribute it and/or
283.10 + * modify it under the terms of the GNU General Public License as
283.11 + * published by the Free Software Foundation; either version 2 of
283.12 + * the License, or (at your option) any later version.
283.13 + *
283.14 + * This program is distributed in the hope that it will be useful,
283.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
283.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
283.17 + * GNU General Public License for more details.
283.18 + *
283.19 + * You should have received a copy of the GNU General Public License
283.20 + * along with this program; if not, write to the Free Software
283.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
283.22 + * Boston, MA 02110-1301, USA
283.23 + */
283.24 +
283.25 +#include <l4/devices/cpm-jz4740.h>
283.26 +#include <l4/devices/gpio-jz4740.h>
283.27 +#include <l4/io/io.h>
283.28 +#include <l4/re/env.h>
283.29 +#include <l4/re/c/mem_alloc.h>
283.30 +#include <l4/re/c/rm.h>
283.31 +#include <l4/re/c/util/cap_alloc.h>
283.32 +#include <l4/sys/cache.h>
283.33 +#include <l4/util/util.h>
283.34 +#include <l4/vbus/vbus.h>
283.35 +
283.36 +#include <stdio.h>
283.37 +#include <stdint.h>
283.38 +
283.39 +#include "nanonote_gpm940b0.h"
283.40 +#include "jzlcd.h"
283.41 +#include "xburst_types.h"
283.42 +#include "memory.h"
283.43 +
283.44 +enum Jz4740_lcd_gpio
283.45 +{
283.46 + Jz4740_lcd_gpio_spen = 21, /* serial command enable */
283.47 + Jz4740_lcd_gpio_spda = 22, /* serial command clock */
283.48 + Jz4740_lcd_gpio_spck = 23, /* serial command data */
283.49 +};
283.50 +
283.51 +/* Peripheral memory regions. */
283.52 +
283.53 +static l4_addr_t cpm_virt_base = 0, cpm_virt_base_end = 0;
283.54 +static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;
283.55 +static l4_addr_t lcd_virt_base = 0, lcd_virt_base_end = 0;
283.56 +
283.57 +/* Device abstractions. */
283.58 +
283.59 +static void *gpio_port_c;
283.60 +static void *cpm_device = 0;
283.61 +static vidinfo_t *panel_info = 0;
283.62 +
283.63 +/* Framebuffer and descriptor regions. */
283.64 +
283.65 +static void *fb_vaddr = 0, *desc_vaddr = 0;
283.66 +static l4_addr_t fb_paddr = 0, desc_paddr = 0;
283.67 +static l4_size_t fb_size, desc_size;
283.68 +
283.69 +
283.70 +
283.71 +// Write SPI values via the LCD GPIO pins.
283.72 +
283.73 +static void spi_write_reg(uint8_t reg, uint8_t val)
283.74 +{
283.75 + uint8_t no;
283.76 + uint16_t value;
283.77 +
283.78 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spen, 1);
283.79 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spck, 1);
283.80 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spda, 0);
283.81 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spen, 0);
283.82 +
283.83 + value = ((reg << 8) | (val & 0xFF));
283.84 +
283.85 + /* Clock data using the clock and data outputs. */
283.86 +
283.87 + for (no = 0; no < 16; no++)
283.88 + {
283.89 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spck, 0);
283.90 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spda, value & 0x8000 ? 1 : 0);
283.91 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spck, 1);
283.92 + value = (value << 1);
283.93 + }
283.94 +
283.95 + jz4740_gpio_set(gpio_port_c, Jz4740_lcd_gpio_spen, 1);
283.96 +}
283.97 +
283.98 +// GPIO-based operations.
283.99 +
283.100 +static void lcd_display_pin_init(void)
283.101 +{
283.102 + Pin_slice mask = {.offset=0, .mask=(1 << Jz4740_lcd_gpio_spen) | (1 << Jz4740_lcd_gpio_spck) | (1 << Jz4740_lcd_gpio_spda)};
283.103 + Pin_slice slcd8_mask = {.offset=0, .mask=0x003c00ff};
283.104 +
283.105 + /* Configure SPI pins. */
283.106 +
283.107 + jz4740_gpio_multi_setup(gpio_port_c, &mask, L4VBUS_GPIO_SETUP_OUTPUT, 0);
283.108 +
283.109 + /* Configure SLCD8 pins. */
283.110 +
283.111 + jz4740_gpio_multi_config_pad(gpio_port_c, &slcd8_mask, Function_alt, 0);
283.112 +}
283.113 +
283.114 +static void lcd_display_on(void)
283.115 +{
283.116 + spi_write_reg(0x05, 0x1e); // GRB=0 (reset); PWM_DUTY=0b011 (70%, default); SHDB2=1, SHDB1=1 (power-related); STB=0 (standby)
283.117 + spi_write_reg(0x05, 0x5e); // GRB=1 (normal operation); ...
283.118 + spi_write_reg(0x07, 0x8d); // HBLK=141 (horizontal blanking period from start of hsync pulse to data start)
283.119 + spi_write_reg(0x13, 0x01); // IN_SEL=1 (alignment mode)
283.120 + spi_write_reg(0x05, 0x5f); // ...; STB=1 (not standby)
283.121 +}
283.122 +
283.123 +/* CPM operations. */
283.124 +
283.125 +static void lcd_set_timing(vidinfo_t *vid)
283.126 +{
283.127 + uint32_t pclk = jz4740_lcd_get_pixel_clock(vid);
283.128 +
283.129 + jz4740_cpm_stop_lcd(cpm_device);
283.130 +
283.131 + /*
283.132 + Original comment: LCDClock > 2.5*Pixclock
283.133 + However, the documentation indicates that a TFT panel needs a device clock
283.134 + 1.5 times that of the pixel clock, and a STN panel needs a device clock 3
283.135 + times that of the pixel clock.
283.136 + */
283.137 +
283.138 + jz4740_cpm_set_lcd_frequencies(cpm_device, pclk, 3);
283.139 + jz4740_cpm_update_output_frequency(cpm_device);
283.140 + jz4740_cpm_start_lcd(cpm_device);
283.141 +
283.142 + l4_sleep(1); // 1ms == 1000us
283.143 +}
283.144 +
283.145 +
283.146 +
283.147 +static int setup_memory(void)
283.148 +{
283.149 + l4re_ds_t fbmem, descmem;
283.150 + l4_size_t fb_size_out, desc_size_out;
283.151 + int result = 0;
283.152 +
283.153 + if (fb_vaddr)
283.154 + return 0;
283.155 +
283.156 + if (!panel_info)
283.157 + return 1;
283.158 +
283.159 + fb_size = jz4740_lcd_get_screen_size(panel_info);
283.160 + desc_size = jz4740_lcd_get_descriptors_size(panel_info);
283.161 +
283.162 + /* Obtain resource details describing the I/O memory. */
283.163 +
283.164 + if ((result = get_memory("jz4740-cpm", &cpm_virt_base, &cpm_virt_base_end)) < 0)
283.165 + return 1;
283.166 +
283.167 + if ((result = get_memory("jz4740-lcd", &lcd_virt_base, &lcd_virt_base_end)) < 0)
283.168 + return 1;
283.169 +
283.170 + if ((result = get_memory("jz4740-gpio", &gpio_virt_base, &gpio_virt_base_end)) < 0)
283.171 + return 1;
283.172 +
283.173 + /* Set the framebuffer up. */
283.174 +
283.175 + fbmem = l4re_util_cap_alloc();
283.176 + descmem = l4re_util_cap_alloc();
283.177 +
283.178 + if (l4_is_invalid_cap(fbmem) || l4_is_invalid_cap(descmem))
283.179 + return 1;
283.180 +
283.181 + /* Allocate memory for the framebuffer at 2**6 == 64 byte == 16 word alignment,
283.182 + also for the descriptors. */
283.183 +
283.184 + if (l4re_ma_alloc_align(fb_size, fbmem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED, 6) ||
283.185 + l4re_ma_alloc_align(desc_size, descmem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED, 6))
283.186 + return 1;
283.187 +
283.188 + /* Map the allocated memory, obtaining virtual addresses. */
283.189 +
283.190 + if (l4re_rm_attach(&fb_vaddr, fb_size,
283.191 + L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP,
283.192 + fbmem, 0, L4_PAGESHIFT) ||
283.193 + l4re_rm_attach(&desc_vaddr, desc_size,
283.194 + L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP,
283.195 + descmem, 0, L4_PAGESHIFT))
283.196 + return 1;
283.197 +
283.198 + fb_size_out = fb_size;
283.199 + desc_size_out = desc_size;
283.200 +
283.201 + if (l4re_ds_phys(fbmem, 0, &fb_paddr, &fb_size_out) ||
283.202 + l4re_ds_phys(descmem, 0, &desc_paddr, &desc_size_out))
283.203 + return 1;
283.204 +
283.205 + if ((fb_size_out != fb_size) || (desc_size_out != desc_size))
283.206 + return 1;
283.207 +
283.208 + cpm_device = jz4740_cpm_init(cpm_virt_base);
283.209 + gpio_port_c = jz4740_gpio_init(gpio_virt_base + 0x200, gpio_virt_base + 0x300, 32);
283.210 +
283.211 + return 0;
283.212 +}
283.213 +
283.214 +static void enable(void)
283.215 +{
283.216 + if (setup_memory())
283.217 + return;
283.218 +
283.219 + jz4740_lcd_set_base(panel_info, (void *) lcd_virt_base);
283.220 + jz4740_lcd_disable(panel_info);
283.221 +
283.222 + // Initialise the LCD controller and structures.
283.223 +
283.224 + jz4740_lcd_ctrl_init(
283.225 + (struct jz_fb_dma_descriptor *) desc_vaddr,
283.226 + (struct jz_fb_dma_descriptor *) desc_paddr,
283.227 + fb_vaddr,
283.228 + (void *) fb_paddr,
283.229 + panel_info);
283.230 +
283.231 + // Initialise the LCD peripheral.
283.232 +
283.233 + jz4740_lcd_hw_init(panel_info);
283.234 +
283.235 + // Initialise the clocks for the LCD controller.
283.236 +
283.237 + lcd_set_timing(panel_info);
283.238 +
283.239 + // Switch the display on using GPIO operations.
283.240 +
283.241 + lcd_display_pin_init();
283.242 + lcd_display_on();
283.243 +
283.244 + // Finally, enable the peripheral.
283.245 +
283.246 + jz4740_lcd_enable(panel_info);
283.247 +}
283.248 +
283.249 +
283.250 +
283.251 +int main(void)
283.252 +{
283.253 + l4_size_t *fb;
283.254 + l4_size_t i, mask, value, onpix, offpix;
283.255 +
283.256 + /* Configure the LCD. */
283.257 +
283.258 + panel_info = &nanonote_panel_info;
283.259 + enable();
283.260 +
283.261 + fb = (l4_size_t *) fb_vaddr;
283.262 +
283.263 + /* Try and show some values. */
283.264 +
283.265 + onpix = 0xffaaffaa; offpix = 0x11551155;
283.266 + mask = 0x80000000; value = 0x80000001;
283.267 +
283.268 + i = 0;
283.269 +
283.270 + while (i < fb_size / 4)
283.271 + {
283.272 + fb[i] = value & mask ? onpix : offpix;
283.273 + i++;
283.274 +
283.275 + if ((i % 10) == 0)
283.276 + {
283.277 + if (mask == 1) mask = 0x80000000;
283.278 + else mask >>= 1;
283.279 +
283.280 + onpix = (onpix >> 8) | ((onpix & 0xff) << 24);
283.281 + offpix = (offpix >> 8) | ((offpix & 0xff) << 24);
283.282 +
283.283 + if (i == 3200) value = jz4740_cpm_get_lcd_pixel_divider(cpm_device);
283.284 + else if (i == 6400) value = jz4740_cpm_get_lcd_pixel_frequency(cpm_device);
283.285 + else if (i == 9600) value = (l4_size_t) fb_vaddr;
283.286 + else if (i == 12800) value = fb_paddr;
283.287 + else if (i == 16000) value = ((struct jz_fb_dma_descriptor *) desc_vaddr)[0].fsadr;
283.288 + else if (i == 19200) value = REG32(lcd_virt_base + 0x00);
283.289 + else if (i == 22400) value = REG32(lcd_virt_base + 0x04);
283.290 + else if (i == 25600) value = REG32(lcd_virt_base + 0x30);
283.291 + else if (i == 28800) value = REG32(lcd_virt_base + 0x40);
283.292 + }
283.293 + }
283.294 +
283.295 + l4_cache_clean_data((long unsigned int) fb_vaddr, (long unsigned int) fb_vaddr + fb_size);
283.296 +
283.297 + while (1);
283.298 +
283.299 + return 0;
283.300 +}
284.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
284.2 +++ b/pkg/landfall-examples/qi_lb60_lcd/xburst_types.h Sun May 13 01:34:16 2018 +0200
284.3 @@ -0,0 +1,31 @@
284.4 +/*
284.5 + * Ingenic XBurst type definitions.
284.6 + *
284.7 + * Copyright 2009 (C) Qi Hardware Inc.
284.8 + * Author: Xiangfu Liu <xiangfu@sharism.cc>
284.9 + * Copyright (C) 2017 Paul Boddie <paul@boddie.org.uk>
284.10 + *
284.11 + * This program is free software: you can redistribute it and/or modify
284.12 + * it under the terms of the GNU General Public License as published by
284.13 + * the Free Software Foundation, either version 3 of the License, or
284.14 + * (at your option) any later version.
284.15 + *
284.16 + * This program is distributed in the hope that it will be useful,
284.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
284.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284.19 + * GNU General Public License for more details.
284.20 + *
284.21 + * You should have received a copy of the GNU General Public License
284.22 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
284.23 + */
284.24 +
284.25 +#ifndef __XBURST_TYPES_H__
284.26 +#define __XBURST_TYPES_H__
284.27 +
284.28 +#include <stdint.h>
284.29 +
284.30 +#define REG8(addr) *((volatile uint8_t *)(addr))
284.31 +#define REG16(addr) *((volatile uint16_t *)(addr))
284.32 +#define REG32(addr) *((volatile uint32_t *)(addr))
284.33 +
284.34 +#endif /* __XBURST_TYPES_H__ */