Skip to content

Commit 10a0f01

Browse files
XenuIsWatchingnashif
authored andcommitted
drivers: i3c: add getmxds ccc helper
Add a CCC helper function for getmxds. Also include it with getting the i3c basic info. Signed-off-by: Ryan McClelland <[email protected]>
1 parent 474431b commit 10a0f01

File tree

3 files changed

+223
-3
lines changed

3 files changed

+223
-3
lines changed

drivers/i3c/i3c_ccc.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,3 +781,100 @@ int i3c_ccc_do_setaasa_all(const struct device *controller)
781781

782782
return i3c_do_ccc(controller, &ccc_payload);
783783
}
784+
785+
int i3c_ccc_do_getmxds(const struct i3c_device_desc *target,
786+
union i3c_ccc_getmxds *mxds,
787+
enum i3c_ccc_getmxds_fmt fmt,
788+
enum i3c_ccc_getmxds_defbyte defbyte)
789+
{
790+
struct i3c_ccc_payload ccc_payload;
791+
struct i3c_ccc_target_payload ccc_tgt_payload;
792+
uint8_t defining_byte;
793+
uint8_t data[5];
794+
uint8_t len;
795+
int ret;
796+
797+
__ASSERT_NO_MSG(target != NULL);
798+
__ASSERT_NO_MSG(target->bus != NULL);
799+
__ASSERT_NO_MSG(mxds != NULL);
800+
801+
ccc_tgt_payload.addr = target->dynamic_addr;
802+
ccc_tgt_payload.rnw = 1;
803+
ccc_tgt_payload.data = &data[0];
804+
805+
if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
806+
/* Could be 2 or 5 Data Bytes Returned */
807+
ccc_tgt_payload.data_len = sizeof(((union i3c_ccc_getmxds *)0)->fmt2);
808+
} else if (fmt == GETMXDS_FORMAT_3) {
809+
switch (defbyte) {
810+
case GETMXDS_FORMAT_3_WRRDTURN:
811+
/* Could be 2 or 5 Data Bytes Returned */
812+
ccc_tgt_payload.data_len =
813+
sizeof(((union i3c_ccc_getmxds *)0)->fmt3.wrrdturn);
814+
break;
815+
case GETMXDS_FORMAT_3_CRHDLY:
816+
/* Only 1 Byte returned */
817+
ccc_tgt_payload.data_len =
818+
sizeof(((union i3c_ccc_getmxds *)0)->fmt3.crhdly1);
819+
break;
820+
default:
821+
ret = -EINVAL;
822+
goto out;
823+
}
824+
} else {
825+
ret = -EINVAL;
826+
goto out;
827+
}
828+
829+
memset(&ccc_payload, 0, sizeof(ccc_payload));
830+
ccc_payload.ccc.id = I3C_CCC_GETMXDS;
831+
ccc_payload.targets.payloads = &ccc_tgt_payload;
832+
ccc_payload.targets.num_targets = 1;
833+
834+
if (fmt == GETMXDS_FORMAT_3) {
835+
defining_byte = (uint8_t)defbyte;
836+
837+
ccc_payload.ccc.data = &defining_byte;
838+
ccc_payload.ccc.data_len = 1;
839+
}
840+
841+
ret = i3c_do_ccc(target->bus, &ccc_payload);
842+
843+
if (ret == 0) {
844+
/* GETMXDS will return a variable length */
845+
len = ccc_tgt_payload.num_xfer;
846+
847+
if ((fmt == GETMXDS_FORMAT_1) || (fmt == GETMXDS_FORMAT_2)) {
848+
if (len == sizeof(((union i3c_ccc_getmxds *)0)->fmt1)) {
849+
mxds->fmt1.maxwr = data[0];
850+
mxds->fmt1.maxrd = data[1];
851+
/* It is unknown wither format 1 or format 2 is returned ahead of
852+
* time
853+
*/
854+
memset(&mxds->fmt2.maxrdturn, 0, sizeof(mxds->fmt2.maxrdturn));
855+
} else if (len == sizeof(((union i3c_ccc_getmxds *)0)->fmt2)) {
856+
mxds->fmt2.maxwr = data[0];
857+
mxds->fmt2.maxrd = data[1];
858+
memcpy(&mxds->fmt2.maxrdturn, &data[2],
859+
sizeof(mxds->fmt2.maxrdturn));
860+
}
861+
} else if (fmt == GETMXDS_FORMAT_3) {
862+
switch (defbyte) {
863+
case GETMXDS_FORMAT_3_WRRDTURN:
864+
memcpy(mxds->fmt3.wrrdturn, data, len);
865+
/* for values not received, assume default (1'b0) */
866+
memset(&mxds->fmt3.wrrdturn[len], 0,
867+
sizeof(mxds->fmt3.wrrdturn) - len);
868+
break;
869+
case GETMXDS_FORMAT_3_CRHDLY:
870+
mxds->fmt3.crhdly1 = data[0];
871+
break;
872+
default:
873+
break;
874+
}
875+
}
876+
}
877+
878+
out:
879+
return ret;
880+
}

drivers/i3c/i3c_common.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <zephyr/toolchain.h>
1111
#include <zephyr/sys/__assert.h>
1212
#include <zephyr/sys/slist.h>
13+
#include <zephyr/sys/byteorder.h>
1314

1415
#include <zephyr/drivers/i3c.h>
1516

@@ -516,6 +517,7 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target)
516517
struct i3c_ccc_mrl mrl = {0};
517518
struct i3c_ccc_mwl mwl = {0};
518519
union i3c_ccc_getcaps caps = {0};
520+
union i3c_ccc_getmxds mxds = {0};
519521

520522
/*
521523
* Since some CCC functions requires BCR to function
@@ -568,6 +570,18 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target)
568570
ret = 0;
569571
}
570572

573+
/* GETMXDS */
574+
if (target->bcr & I3C_BCR_MAX_DATA_SPEED_LIMIT) {
575+
ret = i3c_ccc_do_getmxds_fmt2(target, &mxds);
576+
if (ret != 0) {
577+
goto out;
578+
}
579+
580+
target->data_speed.maxrd = mxds.fmt2.maxrd;
581+
target->data_speed.maxwr = mxds.fmt2.maxwr;
582+
target->data_speed.max_read_turnaround = sys_get_le24(mxds.fmt2.maxrdturn);
583+
}
584+
571585
target->dcr = dcr.dcr;
572586
target->data_length.mrl = mrl.len;
573587
target->data_length.mwl = mwl.len;

include/zephyr/drivers/i3c/ccc.h

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,40 @@ struct i3c_ccc_setbrgtgt {
681681
struct i3c_ccc_setbrgtgt_tgt targets[];
682682
} __packed;
683683

684+
/**
685+
* @brief Indicate which format of getmxds to use.
686+
*/
687+
enum i3c_ccc_getmxds_fmt {
688+
/** GETMXDS Format 1 */
689+
GETMXDS_FORMAT_1,
690+
691+
/** GETMXDS Format 2 */
692+
GETMXDS_FORMAT_2,
693+
694+
/** GETMXDS Format 3 */
695+
GETMXDS_FORMAT_3,
696+
};
697+
698+
/**
699+
* @brief Enum for I3C Get Max Data Speed (GETMXDS) Format 3 Defining Byte Values.
700+
*/
701+
enum i3c_ccc_getmxds_defbyte {
702+
/** Standard Target Write/Read speed parameters, and optional Maximum Read Turnaround Time
703+
*/
704+
GETMXDS_FORMAT_3_WRRDTURN = 0x00U,
705+
706+
/** Delay parameters for a Controller-capable Device, and it's expected Activity State
707+
* during a Controller Handoff
708+
*/
709+
GETMXDS_FORMAT_3_CRHDLY = 0x91U,
710+
711+
/** Invalid defining byte. */
712+
GETMXDS_FORMAT_3_INVALID = 0x100,
713+
};
714+
715+
684716
/**
685717
* @brief Payload for GETMXDS CCC (Get Max Data Speed).
686-
*
687-
* @note This is only for GETMXDS Format 1 and Format 2.
688718
*/
689719
union i3c_ccc_getmxds {
690720
struct {
@@ -716,7 +746,7 @@ union i3c_ccc_getmxds {
716746
*
717747
* @see i3c_ccc_getmxds::fmt2
718748
*/
719-
uint8_t wrrdturn;
749+
uint8_t wrrdturn[5];
720750

721751
/**
722752
* Defining Byte 0x91: CRHDLY
@@ -1830,6 +1860,85 @@ int i3c_ccc_do_setvendor_all(const struct device *controller,
18301860
*/
18311861
int i3c_ccc_do_setaasa_all(const struct device *controller);
18321862

1863+
/**
1864+
* @brief Single target GETMXDS to Get Max Data Speed.
1865+
*
1866+
* Helper function to do GETMXDS (Get Max Data Speed) of
1867+
* one target.
1868+
*
1869+
* This should only be supported if Max Data Speed Limit Bit of
1870+
* the BCR is set
1871+
*
1872+
* @param[in] target Pointer to the target device descriptor.
1873+
* @param[out] caps Pointer to GETMXDS payload.
1874+
* @param[in] fmt Which GETMXDS to use.
1875+
* @param[in] defbyte Defining Byte if using format 3.
1876+
*
1877+
* @return @see i3c_do_ccc
1878+
*/
1879+
int i3c_ccc_do_getmxds(const struct i3c_device_desc *target,
1880+
union i3c_ccc_getmxds *caps,
1881+
enum i3c_ccc_getmxds_fmt fmt,
1882+
enum i3c_ccc_getmxds_defbyte defbyte);
1883+
1884+
/**
1885+
* @brief Single target GETMXDS to Get Max Data Speed (Format 1).
1886+
*
1887+
* Helper function to do GETMXDS (Get Max Data Speed, format 1) of
1888+
* one target.
1889+
*
1890+
* @param[in] target Pointer to the target device descriptor.
1891+
* @param[out] caps Pointer to GETMXDS payload.
1892+
*
1893+
* @return @see i3c_do_ccc
1894+
*/
1895+
static inline int i3c_ccc_do_getmxds_fmt1(const struct i3c_device_desc *target,
1896+
union i3c_ccc_getmxds *caps)
1897+
{
1898+
return i3c_ccc_do_getmxds(target, caps,
1899+
GETMXDS_FORMAT_1,
1900+
GETMXDS_FORMAT_3_INVALID);
1901+
}
1902+
1903+
/**
1904+
* @brief Single target GETMXDS to Get Max Data Speed (Format 2).
1905+
*
1906+
* Helper function to do GETMXDS (Get Max Data Speed, format 2) of
1907+
* one target.
1908+
*
1909+
* @param[in] target Pointer to the target device descriptor.
1910+
* @param[out] caps Pointer to GETMXDS payload.
1911+
*
1912+
* @return @see i3c_do_ccc
1913+
*/
1914+
static inline int i3c_ccc_do_getmxds_fmt2(const struct i3c_device_desc *target,
1915+
union i3c_ccc_getmxds *caps)
1916+
{
1917+
return i3c_ccc_do_getmxds(target, caps,
1918+
GETMXDS_FORMAT_2,
1919+
GETMXDS_FORMAT_3_INVALID);
1920+
}
1921+
1922+
/**
1923+
* @brief Single target GETMXDS to Get Max Data Speed (Format 3).
1924+
*
1925+
* Helper function to do GETMXDS (Get Max Data Speed, format 3) of
1926+
* one target.
1927+
*
1928+
* @param[in] target Pointer to the target device descriptor.
1929+
* @param[out] caps Pointer to GETMXDS payload.
1930+
* @param[in] defbyte Defining Byte for GETMXDS format 3.
1931+
*
1932+
* @return @see i3c_do_ccc
1933+
*/
1934+
static inline int i3c_ccc_do_getmxds_fmt3(const struct i3c_device_desc *target,
1935+
union i3c_ccc_getmxds *caps,
1936+
enum i3c_ccc_getmxds_defbyte defbyte)
1937+
{
1938+
return i3c_ccc_do_getmxds(target, caps,
1939+
GETMXDS_FORMAT_3, defbyte);
1940+
}
1941+
18331942
/**
18341943
* @brief Broadcast DEFTGTS
18351944
*

0 commit comments

Comments
 (0)