Ryzer Posted August 7, 2022 Posted August 7, 2022 After watching a video tutorial on youtube I have attempted to use the build scripts to create a newer image for my Pcduino V2. I had been initially using an image that I found on the archives which uses kernel 4.14, this worked fine for the most part apart from shutting down which would fail 9/10 to shutdown normally. the only way I could ensure that it would shutdown was to do poweroff -f otherwise it just went into a state where most things such as the wifi and usbs would no longer be detected and i was greeted with the message failed to reach target.poweroff. from what I could find out about the issue suggested that it was some kind of issue with systemd, but I could not find an actual solution. Anyway I thought I would have ago at creating an image, I suppose given the age of the board issues are to be expected. I have had some success in fixes some of the issues encountered despite being relatively new to Armbian and Linux in general. After learning how to create patches, firstly I managed to get UART2 which was originally conflicting with the PMU as they shared the same assigned interrupt number of 3. From what I can tell this different to the normal PMU which I find that the power chip is normally referred to as there also appears to be some internal component within the A10 also called the 'PMU' . This seems to be something to do with core monitor as the A20 chip features 2 of these 'PMU's, one for each core. Looking at the user manual suggest that this should be 49. Now this has been patched I can use UART2 without getting an error although it is exposed as ttyS1 for some reason that I have yet to figure out. The second patch I made was to get HDMI output working which I was able to do by using the Cubieboard as a point of reference as they share similar hardware. I found this out by initially using images targeted at the Cubieboard as they appear to be a lot more recent and provide HDMI out so I knew that copying the sections other would. Additionally I found a way to get it working on my main 4K monitor after coming across a post which suggested lowering the size of the CMA buffer from the default size of 128mb to 64mb. Now again the main problem I face is when I try to shutdown, this time it relates to a kernel panic: [ 2508.547646] WARNING: CPU: 0 PID: 1 at drivers/i2c/i2c-core.h:41 i2c_transfer+ 0x93/0xbc [ 2508.561239] No atomic I2C transfer handler for 'i2c-1' [ 2508.571971] Modules linked in: cfg80211 btusb btintel btrtl btbcm bluetooth a xp20x_adc sun4i_gpadc_iio industrialio lima gpu_sched r8188eu(C) sun4i_ts ecdh_g eneric rfkill ecc joydev input_leds sunxi_cedrus(C) v4l2_mem2mem videobuf2_dma_c ontig videobuf2_memops videobuf2_v4l2 videobuf2_common zram evdev uio_pdrv_genir q display_connector uio cpufreq_dt nfsd auth_rpcgss sch_fq_codel nfs_acl lockd g race sunrpc ip_tables x_tables autofs4 pinctrl_axp209 sun4i_gpadc sunxi phy_gene ric gpio_keys icplus(E) [ 2508.635429] CPU: 0 PID: 1 Comm: systemd-shutdow Tainted: G C E 5 .15.32-sunxi #trunk [ 2508.651044] Hardware name: Allwinner sun4i/sun5i Families [ 2508.663328] [<c010cea9>] (unwind_backtrace) from [<c01095b9>] (show_stack+0x1 1/0x14) [ 2508.678114] [<c01095b9>] (show_stack) from [<c09cc035>] (dump_stack_lvl+0x2b/ 0x34) [ 2508.692774] [<c09cc035>] (dump_stack_lvl) from [<c011b5a9>] (__warn+0xad/0xc0 ) [ 2508.707135] [<c011b5a9>] (__warn) from [<c09c5c23>] (warn_slowpath_fmt+0x5f/0 x7c) [ 2508.721785] [<c09c5c23>] (warn_slowpath_fmt) from [<c0795a5f>] (i2c_transfer+ 0x93/0xbc) [ 2508.736949] [<c0795a5f>] (i2c_transfer) from [<c0795ac3>] (i2c_transfer_buffe r_flags+0x3b/0x50) [ 2508.752981] [<c0795ac3>] (i2c_transfer_buffer_flags) from [<c0697577>] (regma p_i2c_write+0x13/0x24) [ 2508.769489] [<c0697577>] (regmap_i2c_write) from [<c0694023>] (_regmap_raw_wr ite_impl+0x48b/0x560) [ 2508.786008] [<c0694023>] (_regmap_raw_write_impl) from [<c0694139>] (_regmap_ bus_raw_write+0x41/0x5c) [ 2508.802806] [<c0694139>] (_regmap_bus_raw_write) from [<c06939b1>] (_regmap_w rite+0x35/0xc8) [ 2508.818874] [<c06939b1>] (_regmap_write) from [<c06948b5>] (regmap_write+0x29 /0x3c) [ 2508.834263] [<c06948b5>] (regmap_write) from [<c069e723>] (axp20x_power_off+0 x23/0x30) [ 2508.850053] [<c069e723>] (axp20x_power_off) from [<c0137ded>] (__do_sys_reboo t+0xf5/0x16c) [ 2508.866244] [<c0137ded>] (__do_sys_reboot) from [<c0100061>] (ret_fast_syscal l+0x1/0x52) [ 2508.882357] Exception stack(0xc154dfa8 to 0xc154dff0) [ 2508.895490] dfa0: 4321fedc bef4aaa8 fee1dead 28121969 4321f edc 00000000 [ 2508.911883] dfc0: 4321fedc bef4aaa8 bef4aaa4 00000058 bef4aaa8 bef4aaa4 fffff 000 bef4aaac [ 2508.928357] dfe0: 00000058 bef4aa1c b6eb81b5 b6e367e6 [ 2508.941715] ---[ end trace 8381275b8efb7dea ]--- [ 2510.584023] i2c i2c-1: mv64xxx: I2C bus locked, block: 1, time_left: 0 [ 2511.128016] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00 000000 [ 2511.175494] CPU: 0 PID: 1 Comm: systemd-shutdow Tainted: G WC E 5 .15.32-sunxi #trunk [ 2511.192848] Hardware name: Allwinner sun4i/sun5i Families [ 2511.206836] [<c010cea9>] (unwind_backtrace) from [<c01095b9>] (show_stack+0x1 1/0x14) [ 2511.223311] [<c01095b9>] (show_stack) from [<c09cc035>] (dump_stack_lvl+0x2b/ 0x34) [ 2511.239614] [<c09cc035>] (dump_stack_lvl) from [<c09c5a4d>] (panic+0xc1/0x238 ) [ 2511.255555] [<c09c5a4d>] (panic) from [<c011fd5d>] (complete_and_exit+0x1/0x1 8) [ 2511.271612] [<c011fd5d>] (complete_and_exit) from [<fee1dead>] (0xfee1dead) [ 2511.287376] ---[ end Kernel panic - not syncing: Attempted to kill init! exit code=0x00000000 ]--- I have seen 1 or 2 other post which appear to be a similar issue. Aside from that SPI does not work, but I gather this is currently a more general issue due to changes in the way the SPIDEV works. it's strange, I can enable the overlay and specify the bus and it shows up under /dev as expected but it does not appear to be sending any date when try to interface with LCD screen. I did a loopback test and it return all zero as if the pins where disconnected. The last version I found it correctly worked on was a Cubieboard image with kernel 5.10. I did come across one post which suggested a possible fix although I'm not sure if this has been implemented yet. I know this probably a bit of a length first post but thanks for taking the time to read and I look forward to hear suggestions of where to start looking next as I know I still have a lot to learn. Here are the logs: http://ix.io/46XA cheers Ryzer 1 Quote
Ryzer Posted March 9, 2023 Author Posted March 9, 2023 Well I finally a solution to the kernel panic on shutdown. I added a patch based on: https://github.com/torvalds/linux/commit/544a8d75f3d6e60e160cd92dc56321484598a993 which addressed the complaint of no atomic handler. diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 43bd2c4f3..3d8b86742 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -150,6 +150,7 @@ struct mv64xxx_i2c_data { /* Clk div is 2 to the power n, not 2 to the power n + 1 */ bool clk_n_base_0; struct i2c_bus_recovery_info rinfo; + bool atomic; }; static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { @@ -179,7 +180,10 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, u32 dir = 0; drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | - MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; + MV64XXX_I2C_REG_CONTROL_TWSIEN; + + if(!drv_data->atomic) + drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_INTEN; if (msg->flags & I2C_M_RD) dir = 1; @@ -409,7 +413,8 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) case MV64XXX_I2C_ACTION_RCV_DATA_STOP: drv_data->msg->buf[drv_data->byte_posn++] = readl(drv_data->reg_base + drv_data->reg_offsets.data); - drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; + if(!drv_data->atomic) + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, drv_data->reg_base + drv_data->reg_offsets.control); drv_data->block = 0; @@ -427,7 +432,8 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) drv_data->rc = -EIO; fallthrough; case MV64XXX_I2C_ACTION_SEND_STOP: - drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; + if(!drv_data->atomic) + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, drv_data->reg_base + drv_data->reg_offsets.control); drv_data->block = 0; @@ -575,6 +581,18 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) spin_unlock_irqrestore(&drv_data->lock, flags); } +static void mv64xxx_i2c_wait_polling(struct mv64xxx_i2c_data *drv_data) +{ + ktime_t timeout = ktime_add_ms(ktime_get(), drv_data->adapter.timeout); + + while (READ_ONCE(drv_data->block) && + ktime_compare(ktime_get(), timeout) < 0) { + udelay(5); + mv64xxx_i2c_intr(0, drv_data); + } + +} + static int mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, int is_last) @@ -590,7 +608,10 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, mv64xxx_i2c_send_start(drv_data); spin_unlock_irqrestore(&drv_data->lock, flags); - mv64xxx_i2c_wait_for_completion(drv_data); + if(!drv_data->atomic) + mv64xxx_i2c_wait_for_completion(drv_data); + else + mv64xxx_i2c_wait_polling(drv_data); return drv_data->rc; } @@ -717,7 +738,7 @@ mv64xxx_i2c_functionality(struct i2c_adapter *adap) } static int -mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +mv64xxx_i2c_xfer_core(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); int rc, ret = num; @@ -730,7 +751,7 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) drv_data->msgs = msgs; drv_data->num_msgs = num; - if (mv64xxx_i2c_can_offload(drv_data)) + if (mv64xxx_i2c_can_offload(drv_data) && !drv_data->atomic) rc = mv64xxx_i2c_offload_xfer(drv_data); else rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1); @@ -747,8 +768,25 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) return ret; } +static int mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); + + drv_data->atomic = 0; + return mv64xxx_i2c_xfer_core(adap, msgs, num); +} + +static int mv64xxx_i2c_xfer_atomic(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); + + drv_data->atomic = 1; + return mv64xxx_i2c_xfer_core(adap, msgs, num); +} + static const struct i2c_algorithm mv64xxx_i2c_algo = { .master_xfer = mv64xxx_i2c_xfer, + .master_xfer_atomic = mv64xxx_i2c_xfer_atomic, .functionality = mv64xxx_i2c_functionality, }; This may not be strictly be necessary as it still failed to shutdown until when looking through the options during the kernel configuration stage of the boot I found the following option: Go to Device drivers > board level reset and power off Then select regulator subsystem power off driver Now when I shutdown the USB and 3v output are successfully turned off. I thought that I should post this on the off chance that it may be usefully to someone with an A10/A20 board. 0 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.