Ryzer Posted August 7, 2022 Share 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 Link to comment Share on other sites More sharing options...
Ryzer Posted March 9, 2023 Author Share 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 Link to comment Share on other sites More sharing options...
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.