| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * Copyright (C) 2024 PHYTEC Messtechnik GmbH |
| * Author: Daniel Schultz <d.schultz@phytec.de> |
| */ |
| |
| #include <asm/arch/hardware.h> |
| |
| #include "am6_som_detection.h" |
| |
| extern struct phytec_eeprom_data eeprom_data; |
| |
| #if IS_ENABLED(CONFIG_PHYTEC_AM62_SOM_DETECTION) || \ |
| IS_ENABLED(CONFIG_PHYTEC_AM64_SOM_DETECTION) |
| |
| /* Check if the SoM is actually one of the following products: |
| * - phyCORE-AM62x |
| * - phyCORE-AM64x |
| * |
| * Returns 0 in case it's a known SoM. Otherwise, returns -1. |
| */ |
| int phytec_am6_detect(struct phytec_eeprom_data *data) |
| { |
| char *opt; |
| u8 som; |
| |
| if (!data) |
| data = &eeprom_data; |
| |
| /* We cannot do the check for early API revisions */ |
| if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) |
| return -1; |
| |
| som = data->payload.data.data_api2.som_no; |
| debug("%s: som id: %u\n", __func__, som); |
| |
| opt = phytec_get_opt(data); |
| if (!opt) |
| return -1; |
| |
| if (som == PHYTEC_AM62X_SOM && soc_is_am62x()) |
| return 0; |
| |
| if (som == PHYTEC_AM64X_SOM && soc_is_am64x()) |
| return 0; |
| |
| return -1; |
| } |
| |
| static u8 phytec_check_opt(struct phytec_eeprom_data *data, u8 option) |
| { |
| char *opt; |
| |
| if (!data) |
| data = &eeprom_data; |
| |
| if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) |
| return PHYTEC_EEPROM_INVAL; |
| |
| if (option > 8) |
| return PHYTEC_EEPROM_INVAL; |
| |
| opt = phytec_get_opt(data); |
| if (opt) |
| return PHYTEC_GET_OPTION(opt[option]); |
| return PHYTEC_EEPROM_INVAL; |
| } |
| |
| /* |
| * Reads LPDDR4 ram size from EEPROM. |
| * |
| * returns: |
| * - The size |
| * - PHYTEC_EEPROM_INVAL when the data is invalid. |
| */ |
| u8 __maybe_unused phytec_get_am6_ddr_size(struct phytec_eeprom_data *data) |
| { |
| u8 ddr_id = phytec_check_opt(data, 3); |
| |
| pr_debug("%s: ddr id: %u\n", __func__, ddr_id); |
| return ddr_id; |
| } |
| |
| /* |
| * Reads SPI-NOR flash size and type from EEPROM. |
| * |
| * returns: |
| * - PHYTEC_EEPROM_VALUE_X if no SPI is poulated. |
| * - Otherwise a board depended code for the size. |
| * - PHYTEC_EEPROM_INVAL when the data is invalid. |
| */ |
| u8 __maybe_unused phytec_get_am6_spi(struct phytec_eeprom_data *data) |
| { |
| u8 spi = phytec_check_opt(data, 5); |
| |
| pr_debug("%s: spi: %u\n", __func__, spi); |
| return spi; |
| } |
| |
| /* |
| * Reads Ethernet phy information from EEPROM. |
| * |
| * returns: |
| * - 0x0 no ethernet phy is populated. |
| * - 0x1 if 10/100/1000 MBit Phy is populated. |
| * - PHYTEC_EEPROM_INVAL when the data is invalid. |
| */ |
| u8 __maybe_unused phytec_get_am6_eth(struct phytec_eeprom_data *data) |
| { |
| u8 eth = phytec_check_opt(data, 6); |
| |
| pr_debug("%s: eth: %u\n", __func__, eth); |
| return eth; |
| } |
| |
| /* |
| * Reads RTC information from EEPROM. |
| * |
| * returns: |
| * - 0 if no RTC is poulated. |
| * - 1 if it is populated. |
| * - PHYTEC_EEPROM_INVAL when the data is invalid. |
| */ |
| u8 __maybe_unused phytec_get_am6_rtc(struct phytec_eeprom_data *data) |
| { |
| u8 rtc = phytec_check_opt(data, 7); |
| |
| pr_debug("%s: rtc: %u\n", __func__, rtc); |
| return rtc; |
| } |
| |
| #else |
| |
| inline int __maybe_unused phytec_am6_detect(struct phytec_eeprom_data *data) |
| { |
| return -1; |
| } |
| |
| inline u8 __maybe_unused |
| phytec_get_am6_ddr_size(struct phytec_eeprom_data *data) |
| { |
| return PHYTEC_EEPROM_INVAL; |
| } |
| |
| inline u8 __maybe_unused phytec_get_am6_spi(struct phytec_eeprom_data *data) |
| { |
| return PHYTEC_EEPROM_INVAL; |
| } |
| |
| inline u8 __maybe_unused phytec_get_am6_eth(struct phytec_eeprom_data *data) |
| { |
| return PHYTEC_EEPROM_INVAL; |
| } |
| |
| inline u8 __maybe_unused phytec_get_am6_rtc(struct phytec_eeprom_data *data) |
| { |
| return PHYTEC_EEPROM_INVAL; |
| } |
| #endif |