Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ipu6-isys-mcd-phy.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2013--2024 Intel Corporation
 */


#include <linux/bits.h>
#include <linux/container_of.h>
#include <linux/device.h>
#include <linux/iopoll.h>
#include <linux/list.h>
#include <linux/refcount.h>
#include <linux/time64.h>

#include <media/v4l2-async.h>

#include "ipu6.h"
#include "ipu6-bus.h"
#include "ipu6-isys.h"
#include "ipu6-isys-csi2.h"
#include "ipu6-platform-isys-csi2-reg.h"

#define CSI_REG_HUB_GPREG_PHY_CTL(id) (CSI_REG_BASE + 0x18008 + (id) * 0x8)
#define CSI_REG_HUB_GPREG_PHY_CTL_RESET   BIT(4)
#define CSI_REG_HUB_GPREG_PHY_CTL_PWR_EN  BIT(0)
#define CSI_REG_HUB_GPREG_PHY_STATUS(id) (CSI_REG_BASE + 0x1800c + (id) * 0x8)
#define CSI_REG_HUB_GPREG_PHY_POWER_ACK   BIT(0)
#define CSI_REG_HUB_GPREG_PHY_READY   BIT(4)

#define MCD_PHY_POWER_STATUS_TIMEOUT   (200 * USEC_PER_MSEC)

/*
 * bridge to phy in buttress reg map, each phy has 16 kbytes
 * only 2 phys for TGL U and Y
 */

#define IPU6_ISYS_MCD_PHY_BASE(i)   (0x10000 + (i) * 0x4000)

/*
 *  There are 2 MCD DPHY instances on TGL and 1 MCD DPHY instance on ADL.
 *  Each MCD PHY has 12-lanes which has 8 data lanes and 4 clock lanes.
 *  CSI port 1, 3 (5, 7) can support max 2 data lanes.
 *  CSI port 0, 2 (4, 6) can support max 4 data lanes.
 *  PHY configurations are PPI based instead of port.
 *  Left:
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | PPI     | PPI5    | PPI4    | PPI3    | PPI2   | PPI1    | PPI0     |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x4      | unused  | D3      | D2      | C0     | D0      | D1       |
 *  |---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x2x2    | C1      | D0      | D1      | C0     | D0      | D1       |
 *  ----------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x2x1    | C1      | D0      | unused  | C0     | D0      | D1       |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x1x1    | C1      | D0      | unused  | C0     | D0      | unused   |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x1x2    | C1      | D0      | D1      | C0     | D0      | unused   |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *
 *  Right:
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | PPI     | PPI6    | PPI7    | PPI8    | PPI9   | PPI10   | PPI11    |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x4      | D1      | D0      | C2      | D2     | D3      | unused   |
 *  |---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x2x2    | D1      | D0      | C2      | D1     | D0      | C3       |
 *  ----------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x2x1    | D1      | D0      | C2      | unused | D0      | C3       |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x1x1    | unused  | D0      | C2      | unused | D0      | C3       |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *  |         |         |         |         |        |         |          |
 *  | x1x2    | unused  | D0      | C2      | D1     | D0      | C3       |
 *  +---------+---------+---------+---------+--------+---------+----------+
 *
 * ppi mapping per phy :
 *
 * x4 + x4:
 * Left : port0 - PPI range {0, 1, 2, 3, 4}
 * Right: port2 - PPI range {6, 7, 8, 9, 10}
 *
 * x4 + x2x2:
 * Left: port0 - PPI range {0, 1, 2, 3, 4}
 * Right: port2 - PPI range {6, 7, 8}, port3 - PPI range {9, 10, 11}
 *
 * x2x2 + x4:
 * Left: port0 - PPI range {0, 1, 2}, port1 - PPI range {3, 4, 5}
 * Right: port2 - PPI range {6, 7, 8, 9, 10}
 *
 * x2x2 + x2x2:
 * Left : port0 - PPI range {0, 1, 2}, port1 - PPI range {3, 4, 5}
 * Right: port2 - PPI range {6, 7, 8}, port3 - PPI range {9, 10, 11}
 */


struct phy_reg {
 u32 reg;
 u32 val;
};

static const struct phy_reg common_init_regs[] = {
 /* for TGL-U, use 0x80000000 */
 {0x00000040, 0x80000000},
 {0x00000044, 0x00a80880},
 {0x00000044, 0x00b80880},
 {0x00000010, 0x0000078c},
 {0x00000344, 0x2f4401e2},
 {0x00000544, 0x924401e2},
 {0x00000744, 0x594401e2},
 {0x00000944, 0x624401e2},
 {0x00000b44, 0xfc4401e2},
 {0x00000d44, 0xc54401e2},
 {0x00000f44, 0x034401e2},
 {0x00001144, 0x8f4401e2},
 {0x00001344, 0x754401e2},
 {0x00001544, 0xe94401e2},
 {0x00001744, 0xcb4401e2},
 {0x00001944, 0xfa4401e2}
};

static const struct phy_reg x1_port0_config_regs[] = {
 {0x00000694, 0xc80060fa},
 {0x00000680, 0x3d4f78ea},
 {0x00000690, 0x10a0140b},
 {0x000006a8, 0xdf04010a},
 {0x00000700, 0x57050060},
 {0x00000710, 0x0030001c},
 {0x00000738, 0x5f004444},
 {0x0000073c, 0x78464204},
 {0x00000748, 0x7821f940},
 {0x0000074c, 0xb2000433},
 {0x00000494, 0xfe6030fa},
 {0x00000480, 0x29ef5ed0},
 {0x00000490, 0x10a0540b},
 {0x000004a8, 0x7a01010a},
 {0x00000500, 0xef053460},
 {0x00000510, 0xe030101c},
 {0x00000538, 0xdf808444},
 {0x0000053c, 0xc8422204},
 {0x00000540, 0x0180088c},
 {0x00000574, 0x00000000},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x1_port1_config_regs[] = {
 {0x00000c94, 0xc80060fa},
 {0x00000c80, 0xcf47abea},
 {0x00000c90, 0x10a0840b},
 {0x00000ca8, 0xdf04010a},
 {0x00000d00, 0x57050060},
 {0x00000d10, 0x0030001c},
 {0x00000d38, 0x5f004444},
 {0x00000d3c, 0x78464204},
 {0x00000d48, 0x7821f940},
 {0x00000d4c, 0xb2000433},
 {0x00000a94, 0xc91030fa},
 {0x00000a80, 0x5a166ed0},
 {0x00000a90, 0x10a0540b},
 {0x00000aa8, 0x5d060100},
 {0x00000b00, 0xef053460},
 {0x00000b10, 0xa030101c},
 {0x00000b38, 0xdf808444},
 {0x00000b3c, 0xc8422204},
 {0x00000b40, 0x0180088c},
 {0x00000b74, 0x00000000},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x1_port2_config_regs[] = {
 {0x00001294, 0x28f000fa},
 {0x00001280, 0x08130cea},
 {0x00001290, 0x10a0140b},
 {0x000012a8, 0xd704010a},
 {0x00001300, 0x8d050060},
 {0x00001310, 0x0030001c},
 {0x00001338, 0xdf008444},
 {0x0000133c, 0x78422204},
 {0x00001348, 0x7821f940},
 {0x0000134c, 0x5a000433},
 {0x00001094, 0x2d20b0fa},
 {0x00001080, 0xade75dd0},
 {0x00001090, 0x10a0540b},
 {0x000010a8, 0xb101010a},
 {0x00001100, 0x33053460},
 {0x00001110, 0x0030101c},
 {0x00001138, 0xdf808444},
 {0x0000113c, 0xc8422204},
 {0x00001140, 0x8180088c},
 {0x00001174, 0x00000000},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x1_port3_config_regs[] = {
 {0x00001894, 0xc80060fa},
 {0x00001880, 0x0f90fd6a},
 {0x00001890, 0x10a0840b},
 {0x000018a8, 0xdf04010a},
 {0x00001900, 0x57050060},
 {0x00001910, 0x0030001c},
 {0x00001938, 0x5f004444},
 {0x0000193c, 0x78464204},
 {0x00001948, 0x7821f940},
 {0x0000194c, 0xb2000433},
 {0x00001694, 0x3050d0fa},
 {0x00001680, 0x0ef6d050},
 {0x00001690, 0x10a0540b},
 {0x000016a8, 0xe301010a},
 {0x00001700, 0x69053460},
 {0x00001710, 0xa030101c},
 {0x00001738, 0xdf808444},
 {0x0000173c, 0xc8422204},
 {0x00001740, 0x0180088c},
 {0x00001774, 0x00000000},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x2_port0_config_regs[] = {
 {0x00000694, 0xc80060fa},
 {0x00000680, 0x3d4f78ea},
 {0x00000690, 0x10a0140b},
 {0x000006a8, 0xdf04010a},
 {0x00000700, 0x57050060},
 {0x00000710, 0x0030001c},
 {0x00000738, 0x5f004444},
 {0x0000073c, 0x78464204},
 {0x00000748, 0x7821f940},
 {0x0000074c, 0xb2000433},
 {0x00000494, 0xc80060fa},
 {0x00000480, 0x29ef5ed8},
 {0x00000490, 0x10a0540b},
 {0x000004a8, 0x7a01010a},
 {0x00000500, 0xef053460},
 {0x00000510, 0xe030101c},
 {0x00000538, 0xdf808444},
 {0x0000053c, 0xc8422204},
 {0x00000540, 0x0180088c},
 {0x00000574, 0x00000000},
 {0x00000294, 0xc80060fa},
 {0x00000280, 0xcb45b950},
 {0x00000290, 0x10a0540b},
 {0x000002a8, 0x8c01010a},
 {0x00000300, 0xef053460},
 {0x00000310, 0x8030101c},
 {0x00000338, 0x41808444},
 {0x0000033c, 0x32422204},
 {0x00000340, 0x0180088c},
 {0x00000374, 0x00000000},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x2_port1_config_regs[] = {
 {0x00000c94, 0xc80060fa},
 {0x00000c80, 0xcf47abea},
 {0x00000c90, 0x10a0840b},
 {0x00000ca8, 0xdf04010a},
 {0x00000d00, 0x57050060},
 {0x00000d10, 0x0030001c},
 {0x00000d38, 0x5f004444},
 {0x00000d3c, 0x78464204},
 {0x00000d48, 0x7821f940},
 {0x00000d4c, 0xb2000433},
 {0x00000a94, 0xc80060fa},
 {0x00000a80, 0x5a166ed8},
 {0x00000a90, 0x10a0540b},
 {0x00000aa8, 0x7a01010a},
 {0x00000b00, 0xef053460},
 {0x00000b10, 0xa030101c},
 {0x00000b38, 0xdf808444},
 {0x00000b3c, 0xc8422204},
 {0x00000b40, 0x0180088c},
 {0x00000b74, 0x00000000},
 {0x00000894, 0xc80060fa},
 {0x00000880, 0x4d4f21d0},
 {0x00000890, 0x10a0540b},
 {0x000008a8, 0x5601010a},
 {0x00000900, 0xef053460},
 {0x00000910, 0x8030101c},
 {0x00000938, 0xdf808444},
 {0x0000093c, 0xc8422204},
 {0x00000940, 0x0180088c},
 {0x00000974, 0x00000000},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x2_port2_config_regs[] = {
 {0x00001294, 0xc80060fa},
 {0x00001280, 0x08130cea},
 {0x00001290, 0x10a0140b},
 {0x000012a8, 0xd704010a},
 {0x00001300, 0x8d050060},
 {0x00001310, 0x0030001c},
 {0x00001338, 0xdf008444},
 {0x0000133c, 0x78422204},
 {0x00001348, 0x7821f940},
 {0x0000134c, 0x5a000433},
 {0x00001094, 0xc80060fa},
 {0x00001080, 0xade75dd8},
 {0x00001090, 0x10a0540b},
 {0x000010a8, 0xb101010a},
 {0x00001100, 0x33053460},
 {0x00001110, 0x0030101c},
 {0x00001138, 0xdf808444},
 {0x0000113c, 0xc8422204},
 {0x00001140, 0x8180088c},
 {0x00001174, 0x00000000},
 {0x00000e94, 0xc80060fa},
 {0x00000e80, 0x0fbf16d0},
 {0x00000e90, 0x10a0540b},
 {0x00000ea8, 0x7a01010a},
 {0x00000f00, 0xf5053460},
 {0x00000f10, 0xc030101c},
 {0x00000f38, 0xdf808444},
 {0x00000f3c, 0xc8422204},
 {0x00000f40, 0x8180088c},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x2_port3_config_regs[] = {
 {0x00001894, 0xc80060fa},
 {0x00001880, 0x0f90fd6a},
 {0x00001890, 0x10a0840b},
 {0x000018a8, 0xdf04010a},
 {0x00001900, 0x57050060},
 {0x00001910, 0x0030001c},
 {0x00001938, 0x5f004444},
 {0x0000193c, 0x78464204},
 {0x00001948, 0x7821f940},
 {0x0000194c, 0xb2000433},
 {0x00001694, 0xc80060fa},
 {0x00001680, 0x0ef6d058},
 {0x00001690, 0x10a0540b},
 {0x000016a8, 0x7a01010a},
 {0x00001700, 0x69053460},
 {0x00001710, 0xa030101c},
 {0x00001738, 0xdf808444},
 {0x0000173c, 0xc8422204},
 {0x00001740, 0x0180088c},
 {0x00001774, 0x00000000},
 {0x00001494, 0xc80060fa},
 {0x00001480, 0xf9d34bd0},
 {0x00001490, 0x10a0540b},
 {0x000014a8, 0x7a01010a},
 {0x00001500, 0x1b053460},
 {0x00001510, 0x0030101c},
 {0x00001538, 0xdf808444},
 {0x0000153c, 0xc8422204},
 {0x00001540, 0x8180088c},
 {0x00001574, 0x00000000},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x4_port0_config_regs[] = {
 {0x00000694, 0xc80060fa},
 {0x00000680, 0x3d4f78fa},
 {0x00000690, 0x10a0140b},
 {0x000006a8, 0xdf04010a},
 {0x00000700, 0x57050060},
 {0x00000710, 0x0030001c},
 {0x00000738, 0x5f004444},
 {0x0000073c, 0x78464204},
 {0x00000748, 0x7821f940},
 {0x0000074c, 0xb2000433},
 {0x00000494, 0xfe6030fa},
 {0x00000480, 0x29ef5ed8},
 {0x00000490, 0x10a0540b},
 {0x000004a8, 0x7a01010a},
 {0x00000500, 0xef053460},
 {0x00000510, 0xe030101c},
 {0x00000538, 0xdf808444},
 {0x0000053c, 0xc8422204},
 {0x00000540, 0x0180088c},
 {0x00000574, 0x00000004},
 {0x00000294, 0x23e030fa},
 {0x00000280, 0xcb45b950},
 {0x00000290, 0x10a0540b},
 {0x000002a8, 0x8c01010a},
 {0x00000300, 0xef053460},
 {0x00000310, 0x8030101c},
 {0x00000338, 0x41808444},
 {0x0000033c, 0x32422204},
 {0x00000340, 0x0180088c},
 {0x00000374, 0x00000004},
 {0x00000894, 0x5620b0fa},
 {0x00000880, 0x4d4f21dc},
 {0x00000890, 0x10a0540b},
 {0x000008a8, 0x5601010a},
 {0x00000900, 0xef053460},
 {0x00000910, 0x8030101c},
 {0x00000938, 0xdf808444},
 {0x0000093c, 0xc8422204},
 {0x00000940, 0x0180088c},
 {0x00000974, 0x00000004},
 {0x00000a94, 0xc91030fa},
 {0x00000a80, 0x5a166ecc},
 {0x00000a90, 0x10a0540b},
 {0x00000aa8, 0x5d01010a},
 {0x00000b00, 0xef053460},
 {0x00000b10, 0xa030101c},
 {0x00000b38, 0xdf808444},
 {0x00000b3c, 0xc8422204},
 {0x00000b40, 0x0180088c},
 {0x00000b74, 0x00000004},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x4_port1_config_regs[] = {
 {0x00000000, 0x00000000}
};

static const struct phy_reg x4_port2_config_regs[] = {
 {0x00001294, 0x28f000fa},
 {0x00001280, 0x08130cfa},
 {0x00001290, 0x10c0140b},
 {0x000012a8, 0xd704010a},
 {0x00001300, 0x8d050060},
 {0x00001310, 0x0030001c},
 {0x00001338, 0xdf008444},
 {0x0000133c, 0x78422204},
 {0x00001348, 0x7821f940},
 {0x0000134c, 0x5a000433},
 {0x00001094, 0x2d20b0fa},
 {0x00001080, 0xade75dd8},
 {0x00001090, 0x10a0540b},
 {0x000010a8, 0xb101010a},
 {0x00001100, 0x33053460},
 {0x00001110, 0x0030101c},
 {0x00001138, 0xdf808444},
 {0x0000113c, 0xc8422204},
 {0x00001140, 0x8180088c},
 {0x00001174, 0x00000004},
 {0x00000e94, 0xd308d0fa},
 {0x00000e80, 0x0fbf16d0},
 {0x00000e90, 0x10a0540b},
 {0x00000ea8, 0x2c01010a},
 {0x00000f00, 0xf5053460},
 {0x00000f10, 0xc030101c},
 {0x00000f38, 0xdf808444},
 {0x00000f3c, 0xc8422204},
 {0x00000f40, 0x8180088c},
 {0x00000f74, 0x00000004},
 {0x00001494, 0x136850fa},
 {0x00001480, 0xf9d34bdc},
 {0x00001490, 0x10a0540b},
 {0x000014a8, 0x5a01010a},
 {0x00001500, 0x1b053460},
 {0x00001510, 0x0030101c},
 {0x00001538, 0xdf808444},
 {0x0000153c, 0xc8422204},
 {0x00001540, 0x8180088c},
 {0x00001574, 0x00000004},
 {0x00001694, 0x3050d0fa},
 {0x00001680, 0x0ef6d04c},
 {0x00001690, 0x10a0540b},
 {0x000016a8, 0xe301010a},
 {0x00001700, 0x69053460},
 {0x00001710, 0xa030101c},
 {0x00001738, 0xdf808444},
 {0x0000173c, 0xc8422204},
 {0x00001740, 0x0180088c},
 {0x00001774, 0x00000004},
 {0x00000000, 0x00000000}
};

static const struct phy_reg x4_port3_config_regs[] = {
 {0x00000000, 0x00000000}
};

static const struct phy_reg *x1_config_regs[4] = {
 x1_port0_config_regs,
 x1_port1_config_regs,
 x1_port2_config_regs,
 x1_port3_config_regs
};

static const struct phy_reg *x2_config_regs[4] = {
 x2_port0_config_regs,
 x2_port1_config_regs,
 x2_port2_config_regs,
 x2_port3_config_regs
};

static const struct phy_reg *x4_config_regs[4] = {
 x4_port0_config_regs,
 x4_port1_config_regs,
 x4_port2_config_regs,
 x4_port3_config_regs
};

static const struct phy_reg **config_regs[3] = {
 x1_config_regs,
 x2_config_regs,
 x4_config_regs
};

static int ipu6_isys_mcd_phy_powerup_ack(struct ipu6_isys *isys, u8 id)
{
 struct device *dev = &isys->adev->auxdev.dev;
 void __iomem *isys_base = isys->pdata->base;
 u32 val;
 int ret;

 val = readl(isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));
 val |= CSI_REG_HUB_GPREG_PHY_CTL_PWR_EN;
 writel(val, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));

 ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id),
     val, val & CSI_REG_HUB_GPREG_PHY_POWER_ACK,
     200, MCD_PHY_POWER_STATUS_TIMEOUT);
 if (ret)
  dev_err(dev, "PHY%d powerup ack timeout", id);

 return ret;
}

static int ipu6_isys_mcd_phy_powerdown_ack(struct ipu6_isys *isys, u8 id)
{
 struct device *dev = &isys->adev->auxdev.dev;
 void __iomem *isys_base = isys->pdata->base;
 u32 val;
 int ret;

 writel(0, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));
 ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id),
     val, !(val & CSI_REG_HUB_GPREG_PHY_POWER_ACK),
     200, MCD_PHY_POWER_STATUS_TIMEOUT);
 if (ret)
  dev_err(dev, "PHY%d powerdown ack timeout", id);

 return ret;
}

static void ipu6_isys_mcd_phy_reset(struct ipu6_isys *isys, u8 id, bool assert)
{
 void __iomem *isys_base = isys->pdata->base;
 u32 val;

 val = readl(isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));
 if (assert)
  val |= CSI_REG_HUB_GPREG_PHY_CTL_RESET;
 else
  val &= ~(CSI_REG_HUB_GPREG_PHY_CTL_RESET);

 writel(val, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));
}

static int ipu6_isys_mcd_phy_ready(struct ipu6_isys *isys, u8 id)
{
 struct device *dev = &isys->adev->auxdev.dev;
 void __iomem *isys_base = isys->pdata->base;
 u32 val;
 int ret;

 ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id),
     val, val & CSI_REG_HUB_GPREG_PHY_READY,
     200, MCD_PHY_POWER_STATUS_TIMEOUT);
 if (ret)
  dev_err(dev, "PHY%d ready ack timeout", id);

 return ret;
}

static void ipu6_isys_mcd_phy_common_init(struct ipu6_isys *isys)
{
 struct ipu6_bus_device *adev = isys->adev;
 struct ipu6_device *isp = adev->isp;
 void __iomem *isp_base = isp->base;
 struct sensor_async_sd *s_asd;
 struct v4l2_async_connection *asc;
 void __iomem *phy_base;
 unsigned int i;
 u8 phy_id;

 list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) {
  s_asd = container_of(asc, struct sensor_async_sd, asc);
  phy_id = s_asd->csi2.port / 4;
  phy_base = isp_base + IPU6_ISYS_MCD_PHY_BASE(phy_id);

  for (i = 0; i < ARRAY_SIZE(common_init_regs); i++)
   writel(common_init_regs[i].val,
          phy_base + common_init_regs[i].reg);
 }
}

static int ipu6_isys_driver_port_to_phy_port(struct ipu6_isys_csi2_config *cfg)
{
 int phy_port;
 int ret;

 if (!(cfg->nlanes == 4 || cfg->nlanes == 2 || cfg->nlanes == 1))
  return -EINVAL;

 /* B,F -> C0 A,E -> C1 C,G -> C2 D,H -> C4 */
 /* normalize driver port number */
 phy_port = cfg->port % 4;

 /* swap port number only for A and B */
 if (phy_port == 0)
  phy_port = 1;
 else if (phy_port == 1)
  phy_port = 0;

 ret = phy_port;

 /* check validity per lane configuration */
 if (cfg->nlanes == 4 && !(phy_port == 0 || phy_port == 2))
  ret = -EINVAL;
 else if ((cfg->nlanes == 2 || cfg->nlanes == 1) &&
   !(phy_port >= 0 && phy_port <= 3))
  ret = -EINVAL;

 return ret;
}

static int ipu6_isys_mcd_phy_config(struct ipu6_isys *isys)
{
 struct device *dev = &isys->adev->auxdev.dev;
 struct ipu6_bus_device *adev = isys->adev;
 const struct phy_reg **phy_config_regs;
 struct ipu6_device *isp = adev->isp;
 void __iomem *isp_base = isp->base;
 struct sensor_async_sd *s_asd;
 struct ipu6_isys_csi2_config cfg;
 struct v4l2_async_connection *asc;
 int phy_port, phy_id;
 unsigned int i;
 void __iomem *phy_base;

 list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) {
  s_asd = container_of(asc, struct sensor_async_sd, asc);
  cfg.port = s_asd->csi2.port;
  cfg.nlanes = s_asd->csi2.nlanes;
  phy_port = ipu6_isys_driver_port_to_phy_port(&cfg);
  if (phy_port < 0) {
   dev_err(dev, "invalid port %d for lane %d", cfg.port,
    cfg.nlanes);
   return -ENXIO;
  }

  phy_id = cfg.port / 4;
  phy_base = isp_base + IPU6_ISYS_MCD_PHY_BASE(phy_id);
  dev_dbg(dev, "port%d PHY%u lanes %u\n", cfg.port, phy_id,
   cfg.nlanes);

  phy_config_regs = config_regs[cfg.nlanes / 2];
  cfg.port = phy_port;
  for (i = 0; phy_config_regs[cfg.port][i].reg; i++)
   writel(phy_config_regs[cfg.port][i].val,
          phy_base + phy_config_regs[cfg.port][i].reg);
 }

 return 0;
}

#define CSI_MCD_PHY_NUM  2
static refcount_t phy_power_ref_count[CSI_MCD_PHY_NUM];

int ipu6_isys_mcd_phy_set_power(struct ipu6_isys *isys,
    struct ipu6_isys_csi2_config *cfg,
    const struct ipu6_isys_csi2_timing *timing,
    bool on)
{
 struct device *dev = &isys->adev->auxdev.dev;
 void __iomem *isys_base = isys->pdata->base;
 u8 port, phy_id;
 refcount_t *ref;
 int ret;

 port = cfg->port;
 phy_id = port / 4;

 ref = &phy_power_ref_count[phy_id];

 dev_dbg(dev, "for phy %d port %d, lanes: %d\n", phy_id, port,
  cfg->nlanes);

 if (!isys_base || port >= isys->pdata->ipdata->csi2.nports) {
  dev_warn(dev, "invalid port ID %d\n", port);
  return -EINVAL;
 }

 if (on) {
  if (refcount_read(ref)) {
   dev_dbg(dev, "for phy %d is already UP", phy_id);
   refcount_inc(ref);
   return 0;
  }

  ret = ipu6_isys_mcd_phy_powerup_ack(isys, phy_id);
  if (ret)
   return ret;

  ipu6_isys_mcd_phy_reset(isys, phy_id, 0);
  ipu6_isys_mcd_phy_common_init(isys);

  ret = ipu6_isys_mcd_phy_config(isys);
  if (ret)
   return ret;

  ipu6_isys_mcd_phy_reset(isys, phy_id, 1);
  ret = ipu6_isys_mcd_phy_ready(isys, phy_id);
  if (ret)
   return ret;

  refcount_set(ref, 1);
  return 0;
 }

 if (!refcount_dec_and_test(ref))
  return 0;

 return ipu6_isys_mcd_phy_powerdown_ack(isys, phy_id);
}

Messung V0.5
C=99 H=98 G=98

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge